-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: apostrophe-issue-richtext #1314
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,31 @@ | ||
import { StoryblokComponent, useStoryblok } from '@storyblok/react'; | ||
import React from 'react'; | ||
import { BrowserRouter, Link, Route, Routes } from 'react-router'; | ||
import Home from './pages/Home'; | ||
import RichtextPage from './pages/RichtextPage'; | ||
|
||
function App() { | ||
const story = useStoryblok('home', { version: 'draft' }); | ||
return ( | ||
<BrowserRouter> | ||
<div> | ||
<nav> | ||
<ul> | ||
<li> | ||
<Link to="/react">Home</Link> | ||
</li> | ||
<li> | ||
<Link to="/react/test-richtext">Richtext</Link> | ||
</li> | ||
</ul> | ||
</nav> | ||
|
||
if (!story?.content) { | ||
return <div>Loading...</div>; | ||
} | ||
|
||
return <StoryblokComponent blok={story.content} />; | ||
<Routes> | ||
<Route path="/" element={<Home />} /> | ||
<Route path="react" element={<Home />} /> | ||
<Route path="react/test-richtext" element={<RichtextPage />} /> | ||
</Routes> | ||
</div> | ||
</BrowserRouter> | ||
); | ||
} | ||
|
||
export default App; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ import { apiPlugin, storyblokInit } from '@storyblok/react'; | |
import IFrameEmbed from './components/iframe-embed'; | ||
|
||
storyblokInit({ | ||
accessToken: 'd6IKUtAUDiKyAhpJtrLFcwtt', | ||
accessToken: 'OurklwV5XsDJTIE1NJaD2wtt', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we need to document which space is associated with these demo token, or it would be a mess to test them later |
||
use: [apiPlugin], | ||
components: { | ||
'teaser': Teaser, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { StoryblokComponent, useStoryblok } from '@storyblok/react'; | ||
import React from 'react'; | ||
|
||
function Home() { | ||
const story = useStoryblok('react', { version: 'draft' }); | ||
|
||
if (!story?.content) { | ||
return <div>Loading...</div>; | ||
} | ||
|
||
return ( | ||
<div> | ||
<h1>Home</h1> | ||
<StoryblokComponent blok={story.content} /> | ||
</div> | ||
); | ||
} | ||
|
||
export default Home; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { StoryblokRichText, useStoryblok } from '@storyblok/react'; | ||
import React from 'react'; | ||
|
||
function RichtextPage() { | ||
const story = useStoryblok('react/test-richtext', { version: 'draft' }); | ||
|
||
if (!story?.content) { | ||
return <div>Loading...</div>; | ||
} | ||
|
||
return ( | ||
story.content.richText && <StoryblokRichText doc={story.content.richText} /> | ||
); | ||
} | ||
|
||
export default RichtextPage; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,11 @@ | ||
import React from 'react'; | ||
|
||
function decodeHtmlEntities(text: string): string { | ||
const textarea = document.createElement('textarea'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this would break in SSR because of the use of |
||
textarea.innerHTML = text; | ||
return textarea.value; | ||
} | ||
|
||
function camelCase(str: string) { | ||
return str.replace(/-([a-z])/g, g => g[1].toUpperCase()); | ||
} | ||
|
@@ -29,6 +35,10 @@ export function convertAttributesInElement(element: React.ReactElement | React.R | |
|
||
// Base case: if the element is not a React element, return it unchanged. | ||
if (!React.isValidElement(element)) { | ||
// If it's a text node, decode any HTML entities | ||
if (typeof element === 'string') { | ||
return decodeHtmlEntities(element) as unknown as React.ReactElement; | ||
} | ||
return element; | ||
} | ||
|
||
|
@@ -55,7 +65,13 @@ export function convertAttributesInElement(element: React.ReactElement | React.R | |
newProps.key = (element.key as string); | ||
|
||
// Process children recursively. | ||
const children = React.Children.map((element.props as React.PropsWithChildren).children, child => convertAttributesInElement(child as React.ReactElement)); | ||
const children = React.Children.map((element.props as React.PropsWithChildren).children, (child) => { | ||
if (typeof child === 'string') { | ||
return decodeHtmlEntities(child); | ||
} | ||
return convertAttributesInElement(child as React.ReactElement); | ||
}); | ||
|
||
const newElement = React.createElement(element.type, newProps, children); | ||
// Clone the element with the new properties and updated children. | ||
return newElement; | ||
|
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 not sure we want to make our React playground dependent on
react-router
honestly, is this needed?