gatsbyjs / gatsby

The best React-based framework with performance, scalability and security built in.
https://www.gatsbyjs.com
MIT License
55.27k stars 10.31k forks source link

[gatsby-source-wordpress] parse specific symbols #13249

Closed yaroslav-perec closed 5 years ago

yaroslav-perec commented 5 years ago

I added a tag with a specific character & to the WP Post when I want to display this tag in my gatsby application, instead of getting just & I get &. Can I avoid this behavior?

wardpeet commented 5 years ago

Hi @yaroslav-perec!

Sorry to hear you're running into an issue. To help us best begin debugging the underlying cause, it is incredibly helpful if you're able to create a minimal reproduction. This is a simplified example of the issue that makes it clear and obvious what the issue is and how we can begin to debug it.

If you're up for it, we'd very much appreciate if you could provide a minimal reproduction and we'll be able to take another look.

Thanks for using Gatsby! 💜

yaroslav-perec commented 5 years ago

Hi @wardpeet!

Thanks for the answer! I think this problem is common, I add screenshots that I think can help you understand what the problem is.

My WP post with tag:

Selection_074

My query:

Selection_075

Can you check it locally?

jonniebigodes commented 5 years ago

@yaroslav-perec can you test something out and see if it fixes or at least help you with it, instead of using & can you try using &. Or in other words, you escape the character/entity and see if it's returned correctly.

yaroslav-perec commented 5 years ago

@jonniebigodes

If in WP I create tag R&D it returns as R&D, R & D returns as R & D

jonniebigodes commented 5 years ago

@yaroslav-perec in my previous comment when i asked to use & instead of & i was hoping that Gatsby and Wordpress were both smart enough(pardon the bad pun) to figure out to return the character already decoded. But based on your response it looks like it doesn't. So I think i have a solution for you, you might need to make make some adjustments but at least this issue will probably will be overcome. Below are the steps i took.

const decode = require("unescape")
const path = require("path")

exports.createPages = ({ actions, graphql }) => {
  const { createPage } = actions
  const templateForWp = path.resolve("./src/templates/blogTemplate.js")
  return graphql(`
    {
      allWordpressPost {
        edges {
          node {
            slug
            title
            content
            tags {
              name
            }
          }
        }
      }
    }
  `).then(result => {
    if (result.errors) {
      throw result.errors
    }
    const { data } = result
    const { allWordpressPost } = data

    allWordpressPost.edges.map(item => {

      createPage({
        path: `/${item.node.slug}/`,
        component: templateForWp,
        context: {
          data_from_wp: {
            title: item.node.title,
            post: item.node.content,
            posttags:item.node.tags!==null?item.node.tags.map(tag=>{
                if (tag.name.includes('&')){
                    return decode(tag.name)
                }
                return tag.name
            }):[]
          },
        },
      })
    })
  })
}

Nothing much different from the standard boilerplate code for a gatsby-node.js file, with the exception being the sanity check for the tags and if there are any, do they contain any special characters in them. All of the data will be injected via Gatsby context prop, i use this as a personal preference and background. I'm biased towards a separation of concerns, to React what is of React, and to Gatsby what is of Gatsby, in short, the component/template/page should only do one job, which is to render what i supplied and gatsby-node.js to fetch all the data either using graphl or rest and supply it where it's needed.

Moving on

import React from 'react';

const BlogTemplate= props=>{
    const {pageContext}= props
    const {data_from_wp}= pageContext

    return (
        <div>
            <h1>{data_from_wp.title}</h1>
            <div style={{border:'2px solid rebeccapurple', margin:'0.8rem'}}>
                This is the content:
                <div>
                    <div dangerouslySetInnerHTML={{ __html: data_from_wp.post }} />
                </div>
                <div>
                    Tags:
                    <ul>
                        {
                            data_from_wp.posttags.map(item=><li>{item}</li>)
                        }
                    </ul>
                </div>

            </div>
        </div>
    )
}
export default BlogTemplate

Issued gatsby develop, waited for the process to complete and opening up the url with the post with special characters showed me the following: special_one

Feel free to provide feedback so that we can close this issue, or if not resolved, to continue to work on it until a solution is found

yaroslav-perec commented 5 years ago

@jonniebigodes

Works! Great thanks for the work done! I think this issue can be closed.

isengartz commented 5 years ago

Hello the same issue exists in post categorie's title too. In Wordpress I have a post category named "Website & Eshop" and in Gatsby it gets replaced to Website &amp; Eshop. In the above example @jonniebigodes save the tags in the context of the Post. I show the category / categories of a post in like 4-5 pages. I think that saving all of categories as context in all above pages is a bit hacky and doesnt sound good. Is there a way to add this functionality to source-plugin directly?

jonniebigodes commented 5 years ago

@isengartz when this issue was created the issue with special characters existed, but looking at what you mentioned it looks like the category data is correct and the special character is working as it should.

The solution i supplied was meant was a way to try and solve the original issue. And don't take me wrong but i don't see it that way, like i said in my response earlier i'm more inclined to make a separation of concerns, by having gatsby-node fetch all the data needed and the page/components only care about displaying it, with that removing the need of an extra graphql query in the page/component for each page. And with that i take full advantage of the gatsby special prop context. And if you don't mind elaborating a bit more on this:

I think that saving all of categories as context in all above pages is a bit hacky and doesnt sound good. Is there a way to add this functionality to source-plugin directly?

From my read on this, a possible solution that probably would suit your needs is to take the same approach as the how it's used by gatsby in the wordpress example and by that you simply fetch the necessary information in gatsby-node.js and in the template component you fetch the information regarding that page/post.

isengartz commented 5 years ago

@jonniebigodes Sorry, I didnt see that github replaced the Website &amp; Eshop to Website & Eshop . I edited my comment above. My bad!

From my read on this, a possible solution that probably would suit your needs is to take the same approach as the how it's used by gatsby in the wordpress example and by that you simply fetch the necessary information in gatsby-node.js and in the template component you fetch the information regarding that page/post.

I already modified everything like that in my project, although I think that the same issue with the special chars that I mentioned for Post Categories will probably exist for other entities too.

jonniebigodes commented 5 years ago

@isengartz no need to apologize, github can be sneaky at times.

From what you said and the original issue description it could be that the problem exists in more than one place, or in other words more than one entity like you said. I haven't checked it fully. But if you want, read the contribution docs, fork the repo, make the necessary adjustments to the plugin in question and submit a pull request, don't forget to mention this issue when you do.