Skip to content

Commit

Permalink
feat(RichText): Add options to force display style
Browse files Browse the repository at this point in the history
  • Loading branch information
raulsteurer committed Jul 18, 2023
1 parent 36e3530 commit dad725c
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 86 deletions.
1 change: 1 addition & 0 deletions src/components/RichText/RichText.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default {
title: 'components/RichText',
component: RichText,
argTypes: {
options: { control: { type: 'object' } },
headingProps: { control: { type: 'object' } },
textProps: { control: { type: 'object' } },
listProps: { control: { type: 'object' } },
Expand Down
27 changes: 27 additions & 0 deletions src/components/RichText/RichText.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,31 @@ function add(a, b) {

expect(screen.getByText('(a, b) {')).toBeInTheDocument();
});

describe('provides an option interface that', () => {
it('forces multi line content as inline', () => {
setup({ options: { forceInline: true } });

expect(screen.getByTestId('rt-wrapper-span')).toBeInTheDocument();
expect(screen.queryByTestId('rt-wrapper-div')).not.toBeInTheDocument();

expect(screen.getByRole('heading', { level: 2 }).parentElement).toBe(
screen.getByTestId('rt-wrapper-span')
);
});

it('forces single line content as a block', () => {
setup({
options: { forceBlock: true },
content: '*Emphasised Text*',
});

expect(screen.getByTestId('rt-wrapper-div')).toBeInTheDocument();
expect(screen.queryByTestId('rt-wrapper-span')).not.toBeInTheDocument();

expect(screen.getByText('Emphasised Text').parentElement).toBe(
screen.getByTestId('rt-wrapper-div')
);
});
});
});
188 changes: 102 additions & 86 deletions src/components/RichText/RichText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export interface RichTextProps {
headingProps?: HeadingProps;
textProps?: TextProps;
listProps?: BoemlyListStyleProps;
options?: {
forceBlock?: boolean;
forceInline?: boolean;
};
}

interface ComponentProps {
Expand Down Expand Up @@ -55,94 +59,106 @@ const SHOULD_RENDER_AS_BLOCK_R = /(\n|^[-*]\s|^#|^ {2,}|^-{2,}|^>\s)/;

export const RichText: React.FC<RichTextProps> = ({
content,
options = {},
headingProps = {},
textProps = {},
listProps = {},
}: RichTextProps) => (
<Markdown
options={{
wrapper: ({ children }: ComponentProps) =>
SHOULD_RENDER_AS_BLOCK_R.test(content) ? (
<Box {...textProps} as="div" data-testid="rt-wrapper-div">
{children}
</Box>
) : (
<Text
size="mdRegularNormal"
color="gray.800"
{...textProps}
as="span"
data-testid="rt-wrapper-span"
>
{children}
</Text>
),
forceWrapper: true,
overrides: {
h1: ({ children }: ComponentProps) => (
<Heading as="h2" size="2xl" mb="6" mt="8" {...headingProps}>
{children}
</Heading>
),
h2: ({ children }: ComponentProps) => (
<Heading as="h3" size="xl" mb="4" mt="6" {...headingProps}>
{children}
</Heading>
),
h3: ({ children }: ComponentProps) => (
<Heading as="h4" size="lg" mb="4" mt="6" {...headingProps}>
{children}
</Heading>
),
h4: ({ children }: ComponentProps) => (
<Heading as="h5" size="md" mb="4" mt="6" {...headingProps}>
{children}
</Heading>
),
p: ({ children }: ComponentProps) => (
<Text size="mdRegularNormal" color="gray.800" mb="12" {...textProps}>
{children}
</Text>
),
span: ({ children }: ComponentProps) => (
<Text size="mdRegularNormal" color="gray.800" {...textProps} as="span">
{children}
</Text>
),
code: ({ className, children }: CodeComponentProps) => {
const language = className ? className.split('-')[1] : 'js';
return (
<Box backgroundColor="primary.50" borderRadius="lg" padding="2" mb="12">
<SyntaxHighlighter
language={language}
style={docco}
customStyle={{ background: 'unset' }}
>
{children}
</SyntaxHighlighter>
}: RichTextProps) => {
let renderInline: boolean = false;

// From https://github.com/probablyup/markdown-to-jsx/blob/7460ee6141fa2449c1b80425c62508af56347268/index.tsx#L1178C47-L1178C47
if (options.forceInline) {
renderInline = true;
} else if (!options.forceBlock) {
renderInline = SHOULD_RENDER_AS_BLOCK_R.test(content) === false;
}

return (
<Markdown
options={{
wrapper: ({ children }: ComponentProps) =>
renderInline ? (
<Text
size="mdRegularNormal"
color="gray.800"
{...textProps}
as="span"
data-testid="rt-wrapper-span"
>
{children}
</Text>
) : (
<Box {...textProps} as="div" data-testid="rt-wrapper-div">
{children}
</Box>
);
),
forceWrapper: true,
overrides: {
h1: ({ children }: ComponentProps) => (
<Heading as="h2" size="2xl" mb="6" mt="8" {...headingProps}>
{children}
</Heading>
),
h2: ({ children }: ComponentProps) => (
<Heading as="h3" size="xl" mb="4" mt="6" {...headingProps}>
{children}
</Heading>
),
h3: ({ children }: ComponentProps) => (
<Heading as="h4" size="lg" mb="4" mt="6" {...headingProps}>
{children}
</Heading>
),
h4: ({ children }: ComponentProps) => (
<Heading as="h5" size="md" mb="4" mt="6" {...headingProps}>
{children}
</Heading>
),
p: ({ children }: ComponentProps) => (
<Text size="mdRegularNormal" color="gray.800" mb="12" {...textProps}>
{children}
</Text>
),
span: ({ children }: ComponentProps) => (
<Text size="mdRegularNormal" color="gray.800" {...textProps} as="span">
{children}
</Text>
),
code: ({ className, children }: CodeComponentProps) => {
const language = className ? className.split('-')[1] : 'js';
return (
<Box backgroundColor="primary.50" borderRadius="lg" padding="2" mb="12">
<SyntaxHighlighter
language={language}
style={docco}
customStyle={{ background: 'unset' }}
>
{children}
</SyntaxHighlighter>
</Box>
);
},
blockquote: ({ children }: ComponentProps) => (
<Box mb="12" pl="4" borderLeft="solid" borderLeftWidth="medium">
{children}
</Box>
),
ul: ({ children }: ListComponentProps) => (
<BoemlyList listItems={getListItems(children)} mb="12" {...listProps} />
),
ol: ({ children }: ListComponentProps) => (
<BoemlyList listItems={getListItems(children)} ordered mb="12" {...listProps} />
),
a: ({ children, href }: LinkComponentProps) => (
<Link size="md" href={href}>
{children}
</Link>
),
img: ({ src, alt }: ImageComponentProps) => <ImageContainer src={src} alt={alt} />,
},
blockquote: ({ children }: ComponentProps) => (
<Box mb="12" pl="4" borderLeft="solid" borderLeftWidth="medium">
{children}
</Box>
),
ul: ({ children }: ListComponentProps) => (
<BoemlyList listItems={getListItems(children)} mb="12" {...listProps} />
),
ol: ({ children }: ListComponentProps) => (
<BoemlyList listItems={getListItems(children)} ordered mb="12" {...listProps} />
),
a: ({ children, href }: LinkComponentProps) => (
<Link size="md" href={href}>
{children}
</Link>
),
img: ({ src, alt }: ImageComponentProps) => <ImageContainer src={src} alt={alt} />,
},
}}
>
{content}
</Markdown>
);
}}
>
{content}
</Markdown>
);
};

0 comments on commit dad725c

Please sign in to comment.