WordPress template using React. Incorrect chars - wordpress

I am creating a WordPress template, using React. I have a WP Post that looks perfect in DB. To retrieve data from the server I use Axios, using the new API feature included in WordPress.
This is how the title looks in the DB:
Hello world! I'm leaving
This is the code I use to retrieve the title from DB:
axios.get('/paintings-project/wp-json/wp/v2/posts').then(
function(response){
self.setState({posts: response.data})
}
);
This is how the post title looks when rendered:
Hello world! I’m leaving
The char ' is escaped, and the backslash used for escaping is encoded.
On the other hand, when rendering HTML content from the post, the HTML appears as a string, instead of rendered as HTML. Like this:
<h1>Welcome’ to WordPress’.</h1> <p><strong>This is your first
post. Edit or delete it, then start writing!</strong></p> <p> </p>
I expected the WordPress APIs would work straight without need of special encoding / decoding in BE or FE. Am I doing something wrong?
Thanks

React doesn't allow you to render strings as HTML in that way. You're going to have to use the dangerouslySetInnerHTML attribute (docs) to render your HTML string in your component.
Something like:
renderStr() {
return {__html: this.state.dataToRender};
},
render() {
return <div dangerouslySetInnerHTML={renderStr()} />;
}
Bear in mind, as the attribute name suggests, you'll want to make sure that the HTML you're rendering is safe. If it's coming from user input, make sure to sanitize the input before storing/rendering it or you can expose yourself and others to security risks. You can use an NPM dependency like sanitizer or sanitize-html, or you can write a function to do it yourself.

Related

How to render JSON content from wordpress API to react component?

I am using WordPress as backend API to fetch data, I have an object is v.post.post_content, the console-log is like this: the console logs the v.post.post_content
however, when I tried to use
dangerouslySetInnerHTML={{
__html: v.post.post_content,
}}
the front end does not look good, as it does not have the CSS format.
I tried to use the react-json-pretty package, however, that is for pure JSON, and it is hard to format a json string contains with texts and HTML tags. Is there a better way to do it?

How to remove __NEXT_DATA__ from dom in NextJs?

Because of NEXT_DATA element dom size is getting very high and it is affecting to the performance. Can anyone plz help me to remove NEXT_DATA from dom?
I am using full server-side rendering with dynamic routes in next Js.
TLDR: If you would(/could) remove the __NEXT_DATA__ script tag, React wouldn't be able to hydrate. You either hardcode the data in the page or try to reduce your pageProps payload, returned from getServerSideProps.
I came upon this issue also recently, where I asked myself, why would there be a need for the content to be included in the HTML 2 times.
As the content itself - when your NextJS renders the appropriate HTML and sends it to the client
As JSON in <script> tag - This is because of the need for rehydration on the client side.
"Solutions"
Returning only necessary data from data-fetching method - I can recommend reading up on this article Reducing HTML payload with NextJS, in which they talk about formatting / aggravating the necessary data and returning only the needed fields.
Not using the data-fetching method and hardcoding static content - The idea behind using static data fetching, if not using revalidate option, is that the content shouldn't be changing (maybe ever). So in that case, why couldn't we hardcode the data in the page itself. Althought downside of this of course is, having to write it all out manually / download the required content to some JSON / object and then use it in the page like so.
Reading
Here's a github link with related discussion in next in which you might be interested.
Blog post about reducing the size of __NEXT_DATA__ - by Liran Cohen.
To remove the rehydration data regex: <script id="__NEXT_DATA__((.|n)*)script> from all pages of the static website run the following command after the build has finished:
find out -name '*.html' | xargs perl -0777 -pi -e 's/<script id="__NEXT_DATA__.*?script>//sg;'
If you come across this issue, make sure you don't have any conditional rendering. This is how I solved this issue myself !
You can do this to not show __NEXT_DATA__:
export const config = {
unstable_runtimeJS: false,
};
But all JavaScript functionality will not work in frontend.
Sometimes you might not require some of the __NEXT_DATA__ props during client side rendering.
To drop those props, you can mutate the NextScript.getInlineScriptSource function in the _document.tsx file. Here is an example:
// _document.tsx
const nextInlineScriptSource = NextScript.getInlineScriptSource;
NextScript.getInlineScriptSource = (props) => {
if (props?.__NEXT_DATA__?.foo) {
props.__NEXT_DATA__.foo = 'bar';
}
return nextInlineScriptSource(props);
};

How to extend the html Twig escaper?

I'm progressively migrating an existing Symfony application to VueJS.
The issue I recently discovered is the {{ stuff }} markup are always interpreted by VueJS, even if the content come from a rendered twig variable.
To avoid this, I would like to extends the html escaper to replace { and } by the respective { and } html codes.
How can I do that properly? The escaping is inside a twig_escape_filter without a service I can override.
I also tried to make a custom escape strategy guesser, returning my vue escaping, itself calling the twig_escape_filter with html escaping before replacing the needed characters. All my source code was escaped. :-D
Thanks for the help.
In fact you could solve this problem in your javascript as simple as that:
import Vue from 'vue';
Vue.options.delimiters = ['${', '}'];
Now you can use double brackets ({{ }}) for twig like you did before and ${ } for VueJs.
EDIT: What you want to do is impossible. You can indeed convert {{ }} to its corresponding html entities using a simple filter like this:
new \Twig_Filter('yourFilter', function ($string) {
return htmlentities($string, ENT_HTML5);
}, ['is_safe' => ['html']])
but since Vue runs on top of your rendered html, the conflict you present will still occur (because html will render these html entities as brackets).
Your only solution is to use a more specific delimeter for your Vue like this one, to avoid this conflict:
Vue.options.delimiters = ['$vue{', '}'];

React app rendering html entities such as ampersand as escaped

I have a React app embedded in Wordpress page. It pulls content from a JSON api and displays it in various areas.
My problem is that all of the text content that comes from the api displays as escaped charachters i.e & displays where an ampersand should be.
My wordpress page has <meta charSet="utf-8" /> which I would normally expect to convert this, but is having no effecton the React content. Is it because the rendering is done within React? In which case do I need to set React somehow to be using UTF-8?
HTML (including entities) will be rendered as a string when being rendered as an expression:
{htmlString}
In order to parse HTML, there is dangerouslySetInnerHTML prop:
<span dangerouslySetInnerHTML={{__html: htmlString }} />
As the name says, it's unsafe and should be generally avoided. If a string comes from untrusted source or a source that could be exploited, malicious code can be rendered to a client.
The preferable way is to decode entities specifically, e.g. with html-entities:
import { Html5Entities } from 'html-entities';
const htmlEntities = new Html5Entities();
...
{htmlEntities.decode(htmlString)}
The problem could be avoided by not storing HTML entities in the first place if possible.

How can I strip html and word formatted text from a text box

I have a multiline textbox, need to restrict users from adding html input, any other scripts, copy pasting from word or any other word processer.
But I need to allow bullets for the input.
I thought it would be a simple thing to do since it looks like a common problem.
But I could not find a good solution in the web, please help.
I am using telerik tool kit as well.
If you need to strip out HTML then HTML Agility Pack is your friend. It will deal with all manner of malformed html. As a bonus it is included in Sitecore already.
If you want to use something with a friendlier syntax then consider CSQuery or Fizzler both of which provide you with a jQuery type syntax from within C#.
If you need to build a whitelist then take a look at this post on how to add whitelist:
public void RemoveNotInWhiteList(HtmlNode pNode, IEnumerable<string> pWhiteList)
{
if (!pWhiteList.Contains(pNode.Name))
{
pNode.Remove();
return;
}
pNode.Attributes
.Where(att => !pWhiteList.Contains(att.Name))
.ToList()
.ForEach(att => att.Remove());
pNode.ChildNodes
.ToList()
.ForEach(att => RemoveNotInWhiteList(att, pWhiteList));
}
You could create a Validation rule, I reckon (in /sitecore/System/Settings/Validation Rules). Put the allowed HTML in a whitelist somewhere (possibly a Sitecore item), when validating run through that whitelist. If any other HTML tags appear in it, make it invalid.
This doesn't stop them from putting it in, but it will stop the item from being published.
You could even create a custom item:saved event handler which strips out all HTML tags apart from the whitelisted stuff. Again, it doesn't stop them from putting the HTML tags in, but as soon as the item is saved it will be removed. Going even a step further than this, I think it also would be possible to use the Rules Engine for this - this article by John West shows how to use the Rules engine to modify item names, but you could modify it to read out specific text boxes.
Neither option here will stop users from inputting HTML, but the HTML tags will automatically be removed when the item is saved.

Resources