I am hitting an API endpoint, which returns the HTML for a blog post as a string. So lots of <p> tags, <img>, <span>, and <div> tags in the response string, with a non-inconsequential amount of element nesting.
in a react app, I want to parse this HTML string, and replace some of the HTML elements (images, paragraphs) with custom react components ( ie wrap an image tag in a lazy-load react component).
what is a good / clean way to do this? trying to parse HTML with regex seems to be an antipattern, and I'm not sure what other possible options there are. parse the string into traditional dom nodes, and then iterate through the collection?
currently I just render the html-as-string inside a react component using dangerouslySetInnerHTML.
What is a reliable, non-regex way to wrap html-as-a-string entities with React components, while maintaining the original order of the nodes (ie in a blog post)?
Take a look at this module and see if it can help you: (https://www.npmjs.com/package/html-to-react). Basically, you can:
Convert html string to React component nodes
Replace the Children of an Element
Related
Summary:
I'm currently migrating a website on Apache + PHP stack over to Node + Express, and would like to know what is the best way/best practice (if there is one) for dynamically injecting meta tags under the new stack.
Details:
Under the existing stack, meta tags are injected dynamically by adding PHP codes into the HTML file directly. As rendering is done on server side, the tags are properly interpreted by Facebook/Google+/whatever web crawlers.
Under the new stack, after doing some research, I've come across two options:
Use template engine like Pug (Jade) to render the HTML with locals. (It seems to be an overkill to rewrite the existing HTML with Pug's syntax though? Can Pug deal with HTML, or I've to consider other template engine like EJS? What template engine do you advise me to explore?)
Use DOM manipulation plugin like Cheerio to inject the meta tags first, before rendering begins.
Between these two options, which one will have a better performance or there is no material difference? Are there any other ways that you'd otherwise recommend? Thanks!
EJS would probably be the simplest one for that and very similar to PHP.
You can also take a look at Mustache and Handlebars for other options with minimal changes to your existing HTML.
with EJS: <html><head><%= yourMetaTags %> ...
with Mustache: <html><head>{{ yourMetaTags }} ...
with Handlebars: <html><head>{{ yourMetaTags }} ...
Also doT.js is very fast.
See:
http://www.embeddedjs.com/
https://mustache.github.io/
http://handlebarsjs.com/
http://olado.github.io/doT/
Parsing the HTML and manipulating it with a DOM API just to insert meta tags would be an overkill in my opinion.
On the other hand if all you need is to insert meta tags then you could make a simple regex substitution, using something like yourHTML.replace('<head>', '<head>'+yourMetaTags); but it could potentially get more complex over time when you need more functionality. After all, everyone has made a templating engine at some point in life.
I have some HTML entered by the user which is displayed in a Yesod template. I would like to transform this HTML, stripping out style attributes from it before it gets rendered, but i cannot find out how.
If my template contains #{ html } i can pass html as a value through a function simply writing #{ transform html }, if the transform function has a signature: transform :: Html -> Html where Html is the type defined by blaze-html here. The problem i see is that Blaze does not seem to expose functionalities useful in order to walk an HTML tree, or even just get the descendents of a given Html. So which strategies would you suggest? Should i try to get into the Blaze internals?
I am not sure whether this should be considered purely an issue with Blaze. Transforming Html elements is not one of the main use cases of Blaze, so this problem needs to be tackled in the context of rendering with Yesod
You have to render to Text or ByteString first, blaze provides no means of analyzing content. Then you can process the data with a library like html-conduit or tagsoup (which is what xss-sanitize does).
Or can you render partially and render rest later. So lets say when app starts up it renders most of the html. But when user abc wants to see his profile jade renders name to abc and merge it with regular pre rendered html and then you send it etc.
Rendering whole html pages at every request seems like a waste.
Converting all static html to jade seems like a annoyance that can be avoided. Slowly css became LESS and html became JADE?
I am lost on how to use jade I am learning express.
You can use Jade's compileClient function to create a function that will render predefined Jade code on the fly. (See the API reference.)
So, if you create a Jade file with the dynamic HTML, and compile that for the client, you can then call that function at a later time, and insert the resulting HTML string to the DOM.
I'm writing a very simple Yesod message list that uses AJAX to add new list items without reloading the page (both in the case of other users modifying the database, or the client themselves adding an item). This means I have to encode the HTML structure of the message items in both the Halmet template (when the page loads initially) and the Julius template (for when the dynamic addition happens). They look something like this:
In homepage.hamlet:
$if not $ null messages
<ul id=#{listId}>
$forall Entity mid message <- messages
<li id=#{toPathPiece mid}>
<p>#{showMarkdown $ messageText message}
<abbr .timeago title=#{showUTCTime $ messagePosted message}>
And in homepage.julius:
function(message) {
$('##{rawJS listId}').prepend(
$('<li>')
.attr('id', message.id)
.append('<p>' + message.text + '</p>')
.append($('<abbr class=timeago />')
.attr('title', message.posted).timeago())
.slideDown('slow')
);
}
I'd love to be able to unify these two representations somehow. Am I out of luck, or could I somehow abuse widgets into both generating an HTML response, and filling in code in a JavaScript file?
Note: Of course, I understand that the templates would have to work very differently, since the AJAX call is getting its values from a JS object, not from the server. It's a long shot, but I thought I'd see if anyone's thought about this before.
I think it's something of a AJAX best-practice to pick one place to do your template rendering, either on the server or client. Yesod is (currently) oriented toward doing the rendering on the server.
This can still work with AJAX replacement of contents, though. Instead of getting a JSON response from the POST, you should get a text/html response that contains the result of rendering the template on the server with the values that would have been returned via JSON and then replacing the innerHTML of the DOM node that's being updated.
If you want to support both JSON and HTML responses (to support 3rd party applications via API or something) you would have to make the format of the response be a function of the request; either appending ".json" or ".html" to the URL or including a HTTP header that lists the specific document type required by the client.
It would be nice if Yesod provided a 'jwhamlet' template or something that would render the HTML via javascript in order to support client rendering, but I'm not aware of one. That's not to say there isn't one I'm not aware of, though, so keep an eye open for other answers.
If you wanted to make such a thing, you might try tweaking the hamlet quasi-quote code so that instead of expanding the quasi-quotes to an html-generating function, it expanded them to a JSON-generating function and a pre-rendered chunk of text that's a template in mustache-style such that the JSON returned by the function would provide the correct context for the template to be rendered the way you want.
I would like to know the possibility to develop custom html tags or custom html attributes to node.js , rather in jade, html or another html template enginer. I was looking at PhantomJS and I don't realize any example that accomplish it, either Cheerio as well. My goal is to make some components to easily usage in any kind of popular html engines. Any direction will be very helpful. Thanks!
Node.js is just a webserver, You need something to parse the custom tags, so its either the template engine that will convert it to valid html, or client side with JavaScript (aka AngularJS directives)
You can write your own filter similar to the example
body
:markdown
Woah! jade _and_ markdown, very **cool**
we can even link to [stuff](http://google.com)
That would give you
<body>
<p>Woah! jade <em>and</em> markdown, very <strong>cool</strong> we can even
link to stuff
</p>
</body>