Closed sarahbethfederman closed 5 years ago
Hey @sarahbethfederman, the transformer plugin only works with raw HTML. If you want to render React component you query the raw data and at rendering, you can use your React components.
Cheers, Khaled
Is there any documentation on how to do this with gatsby? I don't know how to query for a rich text field in graphql without the plugin because it seems you have to specify all the fields and nesting
OK so I figured out how to get the string:
childContentfulRichText {
internal {
content
}
}
and then use that with a custom renderer like so:
import React from 'react'
import { documentToHtmlString } from '@contentful/rich-text-html-renderer';
const { INLINES, BLOCKS, MARKS } = require('@contentful/rich-text-types');
const options = {
renderNode: {
[BLOCKS.PARAGRAPH]: (node, next) => `<p class='spectrum-Body3'>${next(node.content)}</p>`,
[INLINES.HYPERLINK]: (node, next) => {
return `<a class='spectrum-Link' href="${node.data.uri}">${next(node.content)}</a>`
},
[INLINES.ENTRY_HYPERLINK]: (node, next) => {
// TODO figure out how to use gatsby link
return `<a class='spectrum-Link' href=''>${next(node.content)}</a>`
}
}
}
class RichTextRenderer extends React.Component {
render() {
const { content } = this.props;
const JSONContent = JSON.parse(content);
const article = documentToHtmlString(JSONContent, options);
return <div dangerouslySetInnerHTML={{ __html: article }} />;
}
}
RichTextRenderer.propTypes = {};
export default RichTextRenderer;
My questions are now:
Ok update! I figured this out. It seems to be working. I made a documentToJSX function instead and replaced the documentToHTML function in the above.
import escape from 'escape-html';
import React from 'react';
import {
Document,
Mark,
Text,
BLOCKS,
MARKS,
INLINES,
Block,
Inline,
helpers,
} from '@contentful/rich-text-types';
const defaultNodeRenderers = {
[BLOCKS.PARAGRAPH]: (node, next) => <p>{next(node.content)}</p>,
[BLOCKS.HEADING_1]: (node, next) => <h1>{next(node.content)}</h1>,
[BLOCKS.HEADING_2]: (node, next) => <h2>{next(node.content)}</h2>,
[BLOCKS.HEADING_3]: (node, next) => <h3>{next(node.content)}</h3>,
[BLOCKS.HEADING_4]: (node, next) => <h4>{next(node.content)}</h4>,
[BLOCKS.HEADING_5]: (node, next) => <h5>{next(node.content)}</h5>,
[BLOCKS.HEADING_6]: (node, next) => <h6>{next(node.content)}</h6>,
[BLOCKS.EMBEDDED_ENTRY]: (node, next) => <div>{next(node.content)}</div>,
[BLOCKS.UL_LIST]: (node, next) => <ul>{next(node.content)}</ul>,
[BLOCKS.OL_LIST]: (node, next) => <ol>{next(node.content)}</ol>,
[BLOCKS.LIST_ITEM]: (node, next) => <li>{next(node.content)}</li>,
[BLOCKS.QUOTE]: (node, next) => <blockquote>{next(node.content)}</blockquote>,
[BLOCKS.HR]: () => <hr />,
[INLINES.ASSET_HYPERLINK]: node => defaultInline(INLINES.ASSET_HYPERLINK, node),
[INLINES.ENTRY_HYPERLINK]: node => defaultInline(INLINES.ENTRY_HYPERLINK, node),
[INLINES.EMBEDDED_ENTRY]: node => defaultInline(INLINES.EMBEDDED_ENTRY, node),
[INLINES.HYPERLINK]: (node, next) => <a href={node.data.uri}>{next(node.content)}</a>,
};
const defaultMarkRenderers = {
[MARKS.BOLD]: text => <b>{text}</b>,
[MARKS.ITALIC]: text => <i>{text}</i>,
[MARKS.UNDERLINE]: text => <u>{text}</u>,
[MARKS.CODE]: text => <code>{text}</code>,
};
const defaultInline = (type, node) => <span>type: {type} id: {node.data.target.sys.id}</span>;
/**
* Serialize a Contentful Rich Text `document` to JSX.
*/
export function documentToJSX(richTextDocument, options = {}) {
return nodeListToJSX(richTextDocument.content, {
renderNode: {
...defaultNodeRenderers,
...options.renderNode,
},
renderMark: {
...defaultMarkRenderers,
...options.renderMark,
},
});
}
function nodeListToJSX(nodes, { renderNode, renderMark }) {
return nodes.map(node => nodeToJSX(node, { renderNode, renderMark }));
}
function nodeToJSX(node, { renderNode, renderMark }) {
if (helpers.isText(node)) {
const nodeValue = escape(node.value);
if (node.marks.length > 0) {
return node.marks.reduce((value, mark) => {
if (!renderMark[mark.type]) {
return value;
}
return renderMark[mark.type](value);
}, nodeValue);
}
return nodeValue;
} else {
const nextNode = nodes => nodeListToJSX(nodes, { renderMark, renderNode });
if (!node.nodeType || !renderNode[node.nodeType]) {
return null;
}
return renderNode[node.nodeType](node, nextNode);
}
}
only remaining question is what is the best what to grab the entry from the ID
hey @sarahbethfederman usually when you use the SDK to grab the content the entry should be resolved automatically for you. So you will have access to entry.fields
I'm using the Gatsby-source-contentful plugin and it doesn't seem to. Any workarounds?
On Sat, Dec 15, 2018, 1:25 PM Khaled Garbaya notifications@github.com wrote:
hey @sarahbethfederman https://github.com/sarahbethfederman usually when you use the SDK to grab the content the entry should be resolved automatically for you. So you will have access to entry.fields
β You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/contentful/rich-text/issues/46#issuecomment-447598866, or mute the thread https://github.com/notifications/unsubscribe-auth/AFaQmsu_6qcYszuGLpRKFOvV0rSPkhrTks5u5Wi3gaJpZM4ZSXCe .
hey @sarahbethfederman the gatsby-source-contentful is using the SDK under the hood, so it should resolve the entries for you
It doesn't seem to, all I see is the id. How do I check and are there any workarounds?
@sarahbethfederman Thanks for putting together that documentToJSX method :) Hopefully it'll become a part of the plugin. Although I'm not sure how you should override it from gatsby-config.js
due to the difference between node require()
statements vs browser import
statements? I know some projects work around that with Babel, but could trip some users up that don't.
I'm not sure if my approach to converting regular internal hyperlinks into Gatsby Links is much different from the entry kinds you're trying to get working, but maybe it'll be of help to you? I'm parsing the html string into JSX presently rather than using your documentToJSX method(not sure how to get it working with the Link component due to the require/import issue). The logic to convert an anchor tag to a Link component is taken from the Gatsby docs here.
Oh interesting solution! I'll have to check that out. I'm not using the configuration in gatsby-config.js
because I couldn't figure out how to add react to it, and it doesn't really play nice with gatsby's tooling there (no hot reloads or anything). I'm importing the RichTextRenderer
component from above and replaced the line with documentToHTML with documentToJSX, replaced the div with the JSX returned from that, and added a prop to override the component config for specific uses (like telling it to use a different heading class when rendering h3s in the sidebar). It just checks for the prop and returns { options, ...prop.options}
.
The other issue I ran into was because my function returns an array of JSX, I get the each array item must have a unique key warning and haven't figured out a way to add that in, so it's just annoying atm.
The internal links method is probably a better solution than what I was doing which was just using <a>
on hyperlinks and <Link>
on entry_hyperlinks, thanks for that.
Anyway, would definitely be good to have this built in to the plugin! I stripped out all the typescript defs from the original documentToHTML function because we aren't using typescript so it'd need a little work, but happy to try to PR when I have a bit of time (or you're welcome to).
Hey @sarahbethfederman
It doesn't seem to, all I see is the id. How do I check and are there any workarounds?
I think it does work only on the initial sync, when deleting the .cache
folder.
Mainly because the SDK might not have enough data in the payload to resolve these links.
Yikes. That's a pretty massive bug. Do you have any workarounds?
Yikes. That's a pretty massive bug. Do you have any workarounds?
I'm guessing it's due to not having information like when the entity/data was last modified? It's also why I can't ensure that my local/offline support is correct with what's on Contentful.
There's also a similar problem I ran into early into my Contentful use with Gatsby, the gatsby-source-contentful
plugin cached my ContentType for a web page content, which linked to other CMS data like ContentfulAssets, which I hadn't actually published, so in my GraphQL query I wasn't able to retrieve those... publish them then duh! Nope lol, while they did in fact change, the ContentType that was linking to them and was cached hadn't been touched/updated as far as gatsby-source-contentful
(or Contentful itself? Not sure where it gets the information about a change) was concerned.
Perhaps that's the same issue with RichText and and these embedded links? (though I'm confused why they work initially the first time but that data isn't kept afterwards instead of just not able to update like my ContentType with unpublished linked assets experience). I can't actually recall if deleting the cache fixed it or if I had to make some change on Contentful to the ContentType and undo it after to force a changed state(I think this resolved it). I know that with my case, GraphQL schema ignores the fields if none of the results have any data(eg all would return null) which gave added confusion as I knew the field existed on my ContentType.
Does @Khaledgarbaya work at Contentful? If it's a bug on Contentful's end where we can do nothing about it, is avoiding a workaround possible with an actual fix? Surely these would be bugs that can affect Contentful users on paid plans too?
Hey @sarahbethfederman
Yikes. That's a pretty massive bug. Do you have any workarounds?
It is not a bug, as I mentioned the sync API is intended to only return the changed entities so if you don't change a reference it won't be included there and the SDK can't resolve the link unless it does an extra HTTP call which we decided to not do.
@polarathene
Perhaps that's the same issue with RichText and and these embedded links?
It can be yes.
Does @Khaledgarbaya work at Contentful?
π Yes I do.
I am very unclear how resolved entries disappearing is not a bug. Even if it is technically expected on your end, it's entirely unexpected behavior to your users. It makes it unusable to have unresolved entries. Again, is there a workaround you suggest? Do I have to abandon the plugin? Between the lack of react support and entries being unresolved, this plugin is proving to be very frustrating for seemingly basic use cases. Do you plan on fixing these issues or have a timeline in place? Is there an official support channel I can use? I'm on a deadline here and my org is a paying customer.
@polarathene is the entries being unresolved an issue with your method as well?
Again, is there a workaround you suggest?
Deleting the cache should do the trick from what I understand, then the plugin has nothing to compare to and will pull the data down again fresh.
Between the lack of react support and entries being unresolved, this plugin is proving to be very frustrating for seemingly basic use cases.
I don't think it can offer React support in terms of overrides like it does for the HTML strings, unless you go with JSX strings like I did via the JSX parser on component/client side(instead of node). That's due to the conflicting approaches for importing modules afaik. I've been asked about contributing the JSX parser approach which is more of a workaround, you have to write the overrides as JSX wrapped in a string(potentially error prone) and you must also provide the RichText component with the components you intend to use with it(so all possible components you expect could be in the string content). It does work though and no problems so far.
Is there an official support channel I can use? I'm on a deadline here and my org is a paying customer.
As a paying customer it'd probably help raise priority for it :) Though if the JSX parser solution works for you, I could possibly have that contributed within the week(+however long it takes to get reviewed/merged), few other tasks to take care of first.
is the entries being unresolved an issue with your method as well?
Umm I don't have anything too fancy in my RichText content, just web and internal links. I could try reproduce something similar to what you're having trouble with and see though? My similar bug was unrelated to RichText, I had a ContentType with a field that links to ContentfulAssets(images) that I published without publishing the images. That resulted in the field for them being null and omitted in the GraphQL schema. Forcing an update on my ContentType entry via Contentful in the browser fixed that and I could query the field to get ContentfulAssets again.
The internal links you have are resolving properly?
Deleting the cache folder brings up this issue for me so that doesn't help unfortunately. https://github.com/contentful/rich-text/issues/53 The only fix I've found for this is to unpublish all components, and republish them ~4 at a time, building inbetween. :(
The internal links you have are resolving properly?
Well they are just text for me, a hyperlink to nothing related to Contentful, but a different url like mydomain.com/contact, mydomain.com/services.. except to make them internal gatsby links I would have /contact and /services instead.
When I've finished up some other todo items, I'll try out some internal Contentful links? Do you have any examples of what you're linking to? Just another ContentType or an Image asset?
So it looks like contentful only sends the link text for entry_hyperlinks from the API response. https://www.contentful.com/developers/docs/concepts/rich-text/
I don't understand how I'm supposed to link to something with just the link text. There's no way to access the slug unless I do a full embedded entry. I tried using the sys.id that's returned to manually get the entry from the SDK but the id doesn't refer to an existing contentful entry, so I'm not sure what the id is supposed to refer to. I'm going to have to convert every entry-hyperlink to an inline entry just to get the slug I guess.
Where is the sadface emoji reaction? :(
@Khaledgarbaya if this is not something we can contribute a fix for, can you chime in ith Contentful's stance/plans on this?
I understand it's still a beta component and GraphQL is in beta too(though I think Gatsby's GraphQL is separate from that, haven't looked much into how the data is being queried from Contentful.
Hey @sarahbethfederman,
So it looks like contentful only sends the link text for entry_hyperlinks from the API response. contentful.com/developers/docs/concepts/rich-text
if you take a closer look at the payload there is
data: {
target: {
sys: {
id: "7GI6AkMKWIqiiUIuG0uAO",
type: "Link",
linkType: "Entry"
}
}
}
that's the mbedded entry and the SDK be able to resolve the link, it will append
the fields
object to the data.target
Oh yes I see, it just wasn't resolving. Are there plans to fix this so contentful can be used with gatsby develop
? Right now I'm having to build every time I make a change to get entries resolved and it's slow without hot reloading. Here's the cmd for reference: nodemon --watch src --exec 'npm run deploy
Current working code if anyone else is working on this:
https://gist.github.com/sarahbethfederman/04613d376188f71a1995228f33c38328
It looks like nested embedded entries (embedded entries that include an embedded entry) are not resolved, is this being worked on by chance?
@sarahbethfederman I'm not working on anything related to this presently, still chugging away on other tasks.
Looking forward to a response from @Khaledgarbaya about Contentful's stance on how it should be handled(assuming it matters to them to allocate paid hours to it, and/or an issue on their end that we're not able to resolve). He has not really responded about my queries specific to the company's involvement(and may not be able to? Blink twice if you're in danger! :o ).
I haven't looked into using Contentful as much as you are, perhaps you can setup a repo that reproduces the problem? Gatsby repo has a using-contentful example project that has some public secrets iirc, adding a rich-text example there might be a good idea?
Would love to see this get resolved soon. Development is slow without hot reloading.
Based on this issue https://github.com/gatsbyjs/gatsby/issues/10592
It looks like nested embedded entries (embedded entries that include an embedded entry) are not resolved, is this being worked on by chance?
is not an issue
I have also been looking into this for a project and commented on the separate issue #54 around this. One of my first contributions to any project so hopefully I am approaching all of this properly. I think the current working version makes assumptions that the developer is returning a React element in their callbacks and not just a text node or null.
The following should resolve it and feels a lot less hacky since it just uses React helpers. I also does not attempt to overwrite user input keys which might be desirable for something like preserving state by using an embedded assets id as a key:
import React, {isValidElement, cloneElement} from 'react';
const appendKeyToValidElement = (element, key) => {
if (element && isValidElement(element) && element.key === null) {
return cloneElement(element, {key});
}
return element;
};
Full working version in the links below: index.js full repo with tests reworked from html-renderer and some changes to test React specific renders
@mgmolisani, this looks amazing, Please feel free to start a pull request and we can continue from there.
Also want to get opinions on adding the complete document AST to the gatsby-source-contentful schema for rich text. Since we can't put any JSX in our gatsby-config or -node files, the only way to use documentToReactTree
in Gatsby (which was the initial question and my goal) would be calling it in the component tree, either directly or wrapped in the return of a <RichText>
helper component. Either way, it is expecting a document object and feeding it JSON.parse(data.contentfulStuff.key.key)
or JSON.parse(data.contentfulStuff.key.internal.content)
(where key is the API name of the rich text field) just feels like extra steps to remember that could be solved on the source.
I'm no Gatsby plugin expert, but I try to do my homework. The following code in the gatsby-node.js file should add the full document tree as an object to the GraphQL node. Took the naming convention from the remark transformer package.
// gatsby-node.js
const { GraphQLJSON } = require('gatsby/graphql');
exports.setFieldsOnGraphQLNodeType = ({ type }) => {
if (type.name.match(/contentful.*RichTextNode/)) {
return {
contentAST: {
type: GraphQLJSON,
resolve: source => {
// Can also use source.content here, not sure what is best practice vs. most performant
// or if there are gotchas with one or the other
return JSON.parse(source.internal.content);
}
}
};
}
return {};
};
Then, you could just use:
documentToReactTree(data.contenfulStuff.key.contentAST, options)
Not saying this saves a ton of time typing, but to me it feels cleaner than expecting the developer to parse JSON for use with Gatsby and potentially touching the internal
field outside of a plugin. I'm sure there are other use cases for the AST as an object where the extra step of parsing is not desirable.
@mgmolisani just using this now for a project. its working out quite nicely. nice work so far! excited to have this as native in the project
Here is a gist of the same code but with caching. I have no way to tell if caching has any improvement on load time so if you have a beefy rich text node, give it a go. I also noticed Gatsby uses a cache manager that says it resolves with what was stored in the cache... but it actually doesn't which you might better understand from my gist comments. I opened an issue with Gatsby here (which was confirmed in like minutes - go Gatsby!) if you want to help with that.
Having a pretty hard time getting the repo going as npm install
on the forked monorepo doesn't seem to be successfully installing and linking the @contentful/rich-text-types lib. Possibly missing node_modules in @contentful/rich-text-types as well. All tests for libs that have that as a dep end up failing. This behavior is consistent on my PC and my Mac. Not sure if it is just me doing something wrong but this is pretty much step one and I'm pretty stuck. Is anyone else having trouble forking and npm install
and npm run test
? Followed the CONTRIBUTING.md as closely as I could. Seemed straightforward but hasn't worked for me. Help appreciated.
Hi @mgmolisani, I think it's better to use yarn with the monorepo instead of npm
Still no luck with a new clone and yarn install
.
Consistently getting this error in many tests:
1 import { Document, Node, Block, Link, NodeData } from '@contentful/rich-text-types';
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Build seemed to be successful with only 1 hoisting warning.
$ lerna bootstrap --hoist --progress --no-ci
lerna notice cli v3.10.7
lerna info Bootstrapping 6 packages
lerna WARN EHOIST_ROOT_VERSION The repository root depends on @types/jest@^23.3.8, which differs from the more common @types/jest@^23.3.12.
lerna WARN EHOIST_PKG_VERSION "@contentful/rich-text-types" package depends on @types/jest@^23.3.12, which differs from the hoisted @types/jest@^23.3.8.
lerna info Installing external dependencies
lerna info hoist Installing hoisted dependencies into root
lerna info hoist Pruning hoisted dependencies
lerna info hoist Finished pruning hoisted dependencies
lerna info hoist Finished bootstrapping root
lerna info Symlinking packages and binaries
lerna info lifecycle @contentful/gatsby-transformer-contentful-richtext@13.0.0~prepare: @contentful/gatsby-transformer-contentful-richtext@13.0.0
Is there anything else I could provide that might help assess? Maybe I'm missing a global package? Any thoughts?
Interesting discussion though it's hard for me to fully grasp
Could someone here address those questions?
Interesting discussion though it's hard for me to fully grasp
- the issues that remain and
- which approach turned out to work best for rendering Contentful rich text embedded entries using React components.
Could someone here address those questions?
No real issues remain other than I am trying to work on it but having serious issues forking and installing the monorepo. Seems to fail on the types install. Would appreciate if someone else would try and let me know if they are having issues.
Similar approach to documentToHTML
. We tell it what to render in a callback given the raw node and the children post parsing. Keys can be manually set but non manually set keys get prop injected by cloning to valid elements. Be careful with setting keys manually as they should not be index-like (e.g. '1-key' wont clash while "1" might).
Other stuff is just me trying to make the current Gatsby source plugin more usable by all the packages. I am waiting on a pull request getting approved by the Gatsby team (however, that has hit a few road blocks due to potentially breaking changes, so it's back with me for small edits).
Not exactly what this issue was about since this isn't Gatsby specific but npm i -S @contentful/rich-text-react-renderer
is ready for primetime (yay!) and can hopefully help everyone work around the no JSX in the Gatsby config and node files and avoid using dangerouslySetInnerHTML
.
That's great! I've been waiting for this! How would I use that in a Gatsby project? Do I still include gatsby-transformer-contentful-richtext
in my gatsby-config.js
. But then how do I connect that plugin to my documentToReactComponents(document, options)
?
@janosh
How would I use that in a Gatsby project?
documentToReactComponents(document, options)
where document
is the a parsed rich text document which can be accessed by key.key
where key is the API entry title of your rich text node. Consult the docs for more info about options
(very similar to the HTML implementation).
Here is an example of a helper component for consuming this document (I may make a PR to add this to the package).
import PropTypes from 'prop-types';
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';
const RichText = ({ document, options }) => {
return documentToReactComponents(document, options);
};
RichText.propTypes = {
document: PropTypes.object,
options: PropTypes.object,
};
export default RichText;
Do I still include
gatsby-transformer-contentful-richtext
in mygatsby-config.js
.
No. Since JSX is not transpiled in the node and config files (without some serious work arounds anyway), you have to handle this outside the plugin. You will only need the source plugin to get the stringified AST as described above. There is PR for this based on this gist to add the JSON AST in the source plugin so parsing will not be necessary in the future.
@mgmolisani Thanks for the quick response! That's basically what I'm doing (I think, since didn't get the key.key
part). Still I'm getting TypeError: Cannot read property 'map' of undefined
in nodeListToReactComponents
.
richBody
looks like this.
Here's a stripped-down version of my code. Can you see what I'm doing wrong?
import React from "react"
import { graphql } from "gatsby"
import { BLOCKS } from "@contentful/rich-text-types"
import { documentToReactComponents } from "@contentful/rich-text-react-renderer"
import PageTitle from "../components/PageTitle"
const Person = ({ name }) => <h2>{name}</h2>
const options = {
renderNode: {
[BLOCKS.EMBEDDED_ENTRY]: node => {
const { name } = node.data.target.fields
return <Person name={name.de} />
},
},
}
const PageTemplate = ({ data }) => {
const { title, richBody } = data.page
richBody && console.log(documentToReactComponents(richBody, options))
return (
<PageTitle>
<h1>{title}</h1>
</PageTitle>
)
}
export default PageTemplate
export const query = graphql`
query($slug: String!) {
page: contentfulPage(slug: { eq: $slug }) {
title
richBody {
nodeType
content {
nodeType
data {
target {
fields {
name {
de
}
}
}
}
}
}
}
}
`
@janosh Partial trees will likely cause errors with default renderers. In your case, the single paragraph tag is trying to access content
for children but you have not added its content in your graphql query. To resolve this, use:
In your graphql query
...
richBody {
richBody
}
...
And this in the document arg:
JSON.parse(richBody.richBody) // This is the `key.key` part I was talking about
Soon, key.key
will be deprecated in favor of key.json
as an actually object instead of a string which you will no longer need to parse before putting in the document argument so watch out for that.
Awesome! Thanks so much for your help! Never would have thought of JSON.parse(richBody.richBody)
but it's working perfectly! Looking forward to key.json
.
@mgmolisani Do you know if there is or will be a way to transform data on rich text embedded entries? E.g. format date strings with date(formatString: "MMM D, YYYY")
, pass long text fields into gatsby-transformer-remark
or grab gatsby-image
's fixed
or fluid
objects?
The date formatting I assume can already be done by including it into the GraphQL query explicitly rather than just requesting richBody.richBody
(although a site-wide option to return all dates in a certain format would be cool, even if that's something Gatsby would have to implement first and which Contentful rich text could then honor) but the other two seem more difficult.
@janosh I will try to answer these here but you may want to ask some of these in the community Slack channel as they are deviating from this thread. I also do not know Contentful's plans for the future.
Do you know if there is or will be a way to transform data on rich text embedded entries?
This renderer exposes the raw node as the first argument in the callback for exactly this reason. On the entry type of your choosing, pass the date as a prop and handle that prop in your React component however you like (i.e. run it through formatter and display it as children).
// Embed.jsx
const Embed = ({date}) => {
return <h6>{format(date)}</h6>;
};
// Wherever you put your renderer
const options = {
renderNode: {
[BLOCKS.EMBEDDED_ENTRY]: node => {
return <Embed date={node.path.to.date} />
},
},
}
pass long text fields into
gatsby-transformer-remark
Look into remark-react
. Markdown is a standard unlike the rich text AST Contentful produces. There are pretty sophisticated libs out there to handle markdown files.
grab
gatsby-image
'sfixed
orfluid
objects?
I think the source package already does this? Maybe not in the embeds though? If it doesn't, you could probably handle it with a second query on the ID. Not sure, haven't run into a time where I wanted Images as part of my rich text (although I know others do). I actually prefer making 'slices' (many nested references) and pulling more complex structures like lists and images out of the rich text only giving users control over the inline things like marks and links. Check out this page for more gatsby-image info and support.
site-wide option to return all dates in a certain format would be cool
Sounds painful to implement using SaaS instead of your own backend or middleware. You'd have to know very early on you want this to to implement it in every component (either hardcoded or using context). It may be better when making your queries to handle it there or make a transformer plugin to handle it in the specific locations you know it will occur (after all, you build the queries). I can't imagine your main content is dates though so the refactor shouldn't be too stressful if your components are sufficiently separating their duties.
Current working code if anyone else is working on this:
https://gist.github.com/sarahbethfederman/04613d376188f71a1995228f33c38328
When can I found a test repository to see how the code is impletemented please ? I'm quite lost in all the explanations. Have a great day
Hello there,
I am Contentful's product manager working on our Rich Text editor and we recently released an improvement in the gatsby-source-contentful
plugin where it doesn't return a flattened HTML string anymore but the Rich Text AST as a JSON object, with all the embedded entries and assets resolved. Then you can use our rendering libraries in order to render the content into HTML/React/Plain text.
Thank you and let me know if that works.
@martzoukos Very cool! I'm excited to start using Contentful Rich Text in production. Not sure I understand you correctly, though. Does
richBody {
json
}
give me any additional data that wasn't resolved before in
richBody {
richBody
}
@janosh They use the same internals. No difference other than one spits out a string and has a variable name and the other returns an object (which wonβt need to be parsed first like the string version).
Will be closing this issue due to the deprecation of gatsby-transformer-contentful-richtext
package in favour of gatsby-source-contentful
(see https://github.com/contentful/rich-text/issues/46#issuecomment-472797383 and reasons for deprecation for more details).
Feel free to ask any further questions in our community slack channel or send them me directly.
I am wondering what is the correct way to use react with the plugin configuration.
I need to use a gatsby Link component for INLINES.ENTRY_HYPERLINK and not sure how to do so from the gatsby-config file or if there is some other workaround. I have lots of other use cases for using a react component as well.
Can anyone point me in the right direction?