-
Notifications
You must be signed in to change notification settings - Fork 1
feat(components): RichContent component for server HTML #47
base: master
Are you sure you want to change the base?
Conversation
All tests passed! View Coverage Report A Storybook for this PR has been deployed!. It will be accessible as soon as the current build completes. Generated by 🚫 dangerJS |
src/Content/RichContent.js
Outdated
render() { | ||
return ( | ||
this.props.children || ( | ||
<span |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be a fragment, since the contents below the span
could be block level elements
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good eye, I'll make that change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, turns out you can't dangerouslySetInnerHTML
on a Fragment, so it'll have to be a wrapper element. But I'll let 'em specify what it is, and allow props spread.
Leaving @jimbo's Slack comment here: I don't know that the name |
src/Content/RichContent.js
Outdated
return ( | ||
this.props.children || ( | ||
<span | ||
className="peregrine-raw-html" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're not encouraging use of global CSS, so I don't think it's a good idea to have a generic class on here. Would prefer className={this.props.className}
expect(wrapper.html()).toEqual( | ||
'<span class="peregrine-raw-html"><h1 id="o-no">Raw!!!</h1></span>' | ||
); | ||
wrapper = mount( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a separate test case. It's important that, if this one assertion fails, the description of the test failing is clear. Right now, if we have a bug that favors the null
children, the name of the test failing would be Renders raw HTML
, which isn't descriptive of what we're testing (specifically, that we ignore null
children and continue to favor the sanitizedRawHtml
prop).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point; I've changed it.
(As you probably already know), I am a big fan of keeping API surfaces as small as we possibly can until we have an actual need for an API. In this case, I'm not convinced we need the How do you feel about sticking to just the prop until we have a real-world reason to accept |
|
PageBuilder CMS, like many CMSes, will provide raw HTML as a server response. Added a `RichContent` component to handle this common use case. - It uses the `dangerouslySetInnerHTML` API, rendering a string of HTML supplied as a prop. - If the outer system replaces the raw HTML with progressively enhanced functionality, such as a tree of live `ReactElements`, `RichContent` accepts `ReactElements` as children. Children will override the `sanitizedRawHtml` prop. feat(RichContent): Add configurability to wrapper tag - Added two props to configure the "parent element" that React requires to `dangerouslySetInnerHTML`: - `wrapperTag` to specify the tag name as a string - `wrapperProps` to pass an object of props to that tag - Updated docs, stories, and tests to reflect this change feat:retract children API for later
d19436d
to
20d2b3b
Compare
That would be great. And not just "legacy WYSIWYG" - this is useful today for Category Description on category pages, which can (and frequently do) contain raw markup. I'm all for the fallback thing when we get there. I just don't want to take a stab at the API now, because if we're wrong, we're stuck supporting it + something new. |
src/Content/RichContent.js
Outdated
}; | ||
|
||
render() { | ||
// JSX tags must be in PascalCase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/Content/RichContent.js
Outdated
|
||
static defaultProps = { | ||
wrapperTag: 'span', | ||
wrapperProps: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I've seen, it's more common in community React components to just spread any non-own prop into the wrapper in this case. So your render
would be:
render() {
const { wrapperTag: Tag, ...others } = this.props;
return (
<Tag className='peregrine-raw-html' {...others} />
);
}
and you drop wrapperProps
entirely
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm so accustomed to not using object spread for support reasons that I forgot it was an option. I'll change the API.
src/Content/index.js
Outdated
@@ -0,0 +1 @@ | |||
export { default as RichContent } from './RichContent'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should also be re-exported in src/index.js
|
I'll throw my vote in for |
@brendanfalkowski @DrewML Thanks for the feedback, folks. I may be trying to solve a problem of a repetitive pattern I'm anticipating, one that would look a little like this: <Query query={CMS_CONTENT} variables={{ id }}>
{({ loading, error, data }) => {
if (loading) return null;
if (error) return `Error!: ${error}`;
if (data.children) {
return data.children;
}
return (<RawHtml html={data.raw} />)
}}
</Query> But that may end up not being a big hassle. I'll change the component name to |
280d8d2
to
f6f27a6
Compare
- Replace `wrapperProps` with an object spread that automatically removes the custom props from the remaining object - Export component from root
a0e78a3
to
f0b4217
Compare
This PR will need to be re-targeted to the new monorepo. |
This PR is a:
[x] New feature
[ ] Enhancement/Optimization
[ ] Refactor
[ ] Bugfix
[ ] Test for existing code
[ ] Documentation
Summary
PageBuilder CMS, like many CMSes, will provide raw HTML as a server
response. This PR adds a
RichContent
component to handle that common usecase.
When this pull request is merged, it will...
Add the
RichContent
component, its stories, docs, and tests, and expose it as an exported property at the root.Additional information
dangerouslySetInnerHTML
API, rendering a string ofHTML supplied as a prop.
enhanced functionality, such as a tree of live
ReactElements
,RichContent
acceptsReactElements
as children. Children willoverride the
sanitizedRawHtml
prop.