Long story short I have strings that contain HTML which are downloaded before a production build from a secure server. The framework we're using is React with Gatsby and typically you would just do the following:
<div dangerouslySetInnerHTML={{__html: '<p>My Stuff</p>'}}></div>
Which works fine, the main problem is for SEO purposes we want the html to be compiled into html rather than being rendered with Javascript.
Seeing as it's already HTML is there a way I can disable the protection inside react so these strings aren't escaped by default and become regular HTML in the production build?
Not practically, no. It's important to distinguish a <div> in a .jsx file from a <div> in html. If you look at the compiled output of the jsx, it will reveal what's really going on. If you transpile a react component containing <div>Hello world</div>, you'll get a function call along the lines of _react.createElement("div", null, "Hello world"). Anything that is put into the body of the div will also be inserted into it as JSX elements. The dangerouslySetInnerHtml prop is there to tell React that the value is actual html that you trust. However, even if there were an option other than dangerouslySetInnerHtml, I don't believe it would solve your problem as anything inside your react is going to have to wait for client side rendering.
Now, I'm no SEO expert, but if it's crucial to have content on the page before you render it, you may be able to send in the original html in a hidden element. If your original markup has <div id="app">Some seo stuff</div>, React will replace the content of the div when it renders it.
I think what you need is SSR; React allows this feature
You could install a server adapter (maybe expressjs) and use it to render a first screen (which is most likely SEO related) and once the client side is ready to render, it would hydrate the pages. Since you have the HTML gotten from a server, I think this is best route to go
var stringToHTML = function(htmlContent) {
var dom = document.getElementById('integrationMessage');
dom.innerHTML = htmlContent;
return dom;
};
stringToHTML(res.data.message);
<div id = "integrationMessage"></div>
Related
I am learning React.js, and I have noticed that each React file appears to be just a mix of JavaScript and HTML. But I enjoy having distinct files for my HTML and JS. So, I am wondering if I can have these two independent files but also include a link (or something) in either the HTML or JS file, so that they may communicate with one another.
Thank you.
React components implement a render() method that takes input data and returns what to display. This example uses an XML-like syntax called JSX. Input data that is passed into the component can be accessed by render() via this.props.
In other words, it was more simple than we separate html and render it on React, as a component.
If we still want to access html page via any page that created with react, we can did it via a href.
For any other way like import it (maybe), i think it was too complicated because of some reason.
Hope you will more understand about react with this react docs link
React is used to build single-page applications which is an application that loads a single HTML page and all the necessary assets (such as JavaScript and CSS) required for the application to run . this single HTML page is index.html located in the public folder (if you're using create-react-app)
I'm learning React: totally newbie.
If I save in DB the HTML directly from draft.js (or it's variants always based on it) and then in a view page of my React SPA I retrieve HTML from DB through my API:
QUESTIONS:
how can I render that HTML?
dangerouslySetInnerHTML? Or maybe one of this (what do you suggest?)?
https://github.com/wrakky/react-html-parser
https://github.com/pveyes/htmr
https://github.com/remarkablemark/html-react-parser
https://github.com/utatti/react-render-html
https://github.com/aknuds1/html-to-react
I read words like "sanitize", "securing HTML". But how, there is a library?
I need to secure html from draft-js when I save it in DB or after, when I'm rendering it?
Draft-JS doesn't allows you to directly generate HTML from the present EditorState and that's a good thing. Since you are not dealing with "Raw HTML" you don't have to deal with XSS attacks as Draft Editors internal state won't get altered if someone inserts a script in the Editor.
Draft JS allows you the export the current Editor state so that you can store it easily. It can be done using
import {convertToRaw} from 'draft-js';
and in your onChange Handler you can simply do
const editorJSON = JSON.stringify(convertToRaw(editorState.getCurrentContent()));
You can the store this JSON as you like for future use.
Now for Rendering this you have two options :
Generate HTML from the stored EditorState.
This can be done using Libraries like https://www.npmjs.com/package/draft-js-export-html. You might want to avoid this as the next option in my opinion is way better.
Use this EditorState as the Default value for a read only DraftJS Editor Component.
You are going to need convertFromRaw from DraftJS Library and then you make a Nice StateLess React Component like this
import React from 'react';
import {Editor, ConvertFromRaw} from 'draft-js';
const ReadOnlyEditor = (props) => {
const storedState = ConvertFromRaw(JSON.parse(props.storedState));
return (
<div className="readonly-editor">
<Editor editorState={storedState} readOnly={true} />
</div>
);
}
And Now you can simply use this to display your contents. You can also pass your decorators and custom mapping functions, typically everything you pass to the normal Editor and can render the content without loss of style and tedious dealing with HTML.
DO NOT Believe USERS!
The first thing you should care of is "Do NOT believe your USERS".
If your 'HTML' is rendered by your server and can't be modified by user, it's totally OK.
Because your rendered/saved HTML is totally safe and managed by yourself, and if it's assured as "SAFE" HTML, whether you put it(html) into DOM or not is not the problem at all.
But the problem is, most of WYSIWYG editors - like draft.js- makes "HTML" files not TEXT. I think your worry comes from here too.
Yes, It's dangerous. what we can do is NOT rendering HTML directly but "selective" HTML rendering.
Dangerous tags : <script>, <img>, <link>, etc.
you can remove those tags but it can be much safer when you decide which tags will you allow, like this:
Safe tags: <H1> - <H6> / span / div / p / ol ul li / table...
and you SHOULD remove those HTML element's attributes, like, onclick="", etc.
because it could be abused by users too.
Conclusion:
So what can we do when we use WYSIWYG editors?
There are 2 big strategies:
Generate "Safe" HTML when safe to Database.
Generate "Safe" HTML before putting it into DOM.
(3. Generate "Safe" HTML before sending html to client, but it is not in your case!)
Choose first one if you want to sure Database's text are totally safe.
First one must be processed in your server(not browser/client!), and you can use many solutions like BeautifulSoup in python, or sanitize-html in nodejs.
Choose second one if your web-app is complicated, and most of your service's business logic is running on front-end side.
Second one is using HTML escaping package just before mounting HTML into DOM. and still sanitize-html can be good solution. (surelly there's more great solutions!)
You can decide which tags/attribute/values in HTML.
Links
https://github.com/punkave/sanitize-html
in 2022 for me, it works a bit different way
import { convertFromRaw, Editor, EditorState } from 'draft-js';
function Comments() {
const itemText= EditorState.createWithContent(convertFromRaw(JSON.parse(item.content)));
return <Editor editorState={itemText} readOnly={true} />
}
and to the DB it was saved like that
JSON.stringify(convertToRaw(editorState.getCurrentContent()))
the difference is that for me without EditorState it doesn't work, I believe that I am not alone in that
I have a component in Ember2 that receives a parameter {{my-component product=p}}. I need to pre compile the component and get the generated html.
I have tried to use ember-cli-htmlbars-inline-precompile but without success. let template = hbs"{{mycomponent product=p }};
First its important to clarify the terms. Compiling a component does not mean to produce HTML! It basically means to produce a bytecode that can be used with the glimmer runtime to produce and update DOM. Ember will never produce HTML, and this is important to understand.
If you think ember produces HTML and then gives that to the browser to render you are wrong.
Ember directly produces DOM, and then keeps track of the DOM nodes to update the DOM and allow live binding.
So basically there is no public API in ember to do what you want.
Of course you can just render the component, and use this.element.outerHTML to access the HTML. But remember that with that you will lose all ember functionality like live-binding or actions.
This is especially tricky because google maps renders all into an iframe.
ember-wormhole shows that its possible to render ember content outside the main div, but they make use of private API and I think this possibility ends with the iframe.
In my leisure time I'm currenty building my first react app (page builder) and it should be easily scalable by user without using npm. It should work at runtime.
For that I would like to write a Component that has exchangeable markup, so when a user prefers to say this.state.text = "Hello World! should be inside a <p>{this.state.text}</p> instead of a <h1>{this.state.text}</h1>
He can change that without injecting the compiled (and minified) react code.
Currently I'm using the Fetch API to render the markup with PHP but on every state change it calls the server and that needs < 3 seconds every time, so no fast realtime rendering.
First question: Is there a way to use this sever side rendering approach without any delay or micro-delay?
I already read about Mustache and handlebars.js, therefore I need to write a runtime library to convert the props into mustache or handlebars to render it with dangerouslySetInnerHTML. But this is vulnerable.
Second question: I could escape the mustache or handlebar markup with PHP before it outputs, but I don't know if this is save enough?
Third question: Besides, is there a huge performance break to use dangerouslySetInnerHTML?
The best approach I could find so far was react-templates by WIX, but it needs npm.
Fourth question: Do you know any other/better approach to achieve my goal of exchangable markup?
I have a piece of code that server sends to react component and this piece of code is set as a component property. This code includes a div tag and a script tag inside it. I need to execute and run this code in React component. Dangerously Set innerHTML doesn't work for me - js code isn't running in this case. Are there any variants to make this work?
Thanks in advance.
You can still use eval() for this.
But you need to be aware of the security implications it has. Especially you need to make sure you are using secure connections to your server and don't publish malicious code to your users.
React does not recommends use innerHTML. But if you very need to, you can use
function createMarkup() { return {__html: 'First ยท Second'}; };
<div dangerouslySetInnerHTML={createMarkup()} />
More info https://facebook.github.io/react/tips/dangerously-set-inner-html.html