React/Phoenix - escaping HTML will briefly flash unrendered HTML in browser - html

I'm running a React/Phoenix app that uses server-side rendering, and I'm finding that when I refresh the app rapidly, I can for a split second see the unrendered HTML from the server in the browser before it all renders correctly. This only happens to HTML that is escaped, but I want to use escaped HTML for this app as I don't want the browser to assume that it is safe. This happens in Chrome and Firefox, but not in Safari.
The app was scaffolded using RePh (which I highly recommend) - https://github.com/reph-stack/reph - and the relevant controller is:
defmodule MyAppWeb.ReactController do
use MyAppWeb, :controller
def index(conn, _params) do
initial_state = %{}
react_stdio_args = %{
component: Application.app_dir(:my_app, "priv/static/server/js/app.js"),
props: %{
"location" => conn.request_path,
"initial_state" => initial_state
}
}
{:ok, %{"html" => html}} = StdJsonIo.json_call(react_stdio_args)
render(conn, "index.html", html: html, initial_state: initial_state)
end
end
which pipes data to index.html.eex:
<div id="index"><%= #html %></div>
<script>__INITIAL_STATE__=<%= #initial_state |> Poison.encode! |> raw %></script>
In the default setup for this scaffold, the #html is marked as safe with raw - <%= raw #html %> - but as you can see, I've removed that.
So anyway, if I refresh the browser window at a 'reasonable' pace, there's no problem... but if I start refreshing quickly, I can briefly see the unrendered HTML in the browser window, something like:
<div class="AppContainer wrapper" data-reactroot="" data-reactid="1" data-react-checksum="-1859726426"><header class="site-header" data-reactid="2"> etc...
Needless, to say, this does not happen if I leave raw in. I've tried some other escaping methods as well, such as Phoenix.HTML.html_escape(html) in the controller, but the same problem occurs.
I imagine that this happens because the browser needs that tiny sliver of a second to properly parse and render the escaped HTML, and the differences in browser performance can be chalked up to the different layout engines (perhaps?)... but I'm not an expert in these matters, so I don't know for sure. Is there any way that I can force my app to wait until the HTML is properly rendered before displaying it for the user?

#html here is a string of HTML. You cannot make it "safer" by removing raw. Removing raw will escape all the < and > in the string making the browser show the raw HTML code. You need to use raw here for SSR to work correctly. You can see this behavior if you try the following:
<%= raw "<strong>Raw</strong>" %>
<%= "<strong>Escaped</strong>" %>

Related

Is it possible to change the way rails renders a small piece of code

I'm trying to set up VideoJS and I'm following the guide here.
You'll see that for automatic setup the video needs to be initialized like this:
<video class="video-js" data-setup='{}'>
Which I thought would be fine because in rails I can do this:
<%= video_tag #video.filename + '.mp4', :class => 'video-js', 'data-setup' => '{}' %>
However, that renders the tag like this:
<video class="video-js" data-setup="{}" src="/assets/0019 Trump Android.mp4"></video>
That looks fine at first glance except that the data-setup line needs single quotes, not double quotes, or videojs setup won't work. Like this: data-setup='{}'
So is there any way to get rails to render that one attribute with single quotes instead of double quotes?
Also, a second thought, why should I have rails render the video tag when I could just write it in HTML?
Helpers are just there to make things easier to read syntactically, and easier to program. If you write HTML instead of ERB it performs the same, provided your HTML tags print out everything ERB would have otherwise printed.
In this specialized usecase, I would just write the entire HTML tag surrounded by an ERB .each tag. Not sure how you have your controller set up, but under the assumption it was something like #videos = Videos.all, it would be something like this:
<% #videos.each do |video| %>
<video class="video-js" data-setup='{}' src=<%=video.file_name%>>
</video>
<% end %>
The video_tag helper does have some use like the poster attribute which references an image, so it's needed for that, to include the digest of the image file. However for your use case I don't see any reason to use the helper when it's quite easy to just write the pure html yourself.

How to use html_safe and convert links to absolute URLs (not relative URLs)

In Rails, how can I render stored HTML and display it with working, absolute links? I have a chunk of HTML that I am calling html_safe on from a view page. When I load the page in the browser, all of the links from that HTML render as relative URLs on my own domain rather than absolute links to the original destination.
In my console or as a result of a form:
#company.about = "Some info about a company."
In the view:
<%= #company.about.html_safe %>
What renders in the browser (relative URL):
Some info about a company.
What I would like to render in the browser (absolute URL):
Some info about a company.
PS - I realize that doing this isn't great practice. But it's not user-submitted content, just my own. And it's a temporary workflow until I decide how to better structure my model to accommodate these links. I'm more surprised that can't find more detailed information on what html_safe actually does w/r/t to links.
I've tested this on my rails app, and run (check how i use ' and "):
#company.about = 'Some info about a company.'
<%= #company.about.html_safe %>
have you tried with raw?
<%= raw #company.about %>
or something so (it's not tested, i use this method into prawn, maybe can run:
#company.about = "Some info about a #{company}."
Personal suggestion. You can save your about column as markdown text.
Then use redcarpet or something markdown gem to translate model content to html text.
It's safer (redcarpet will deal with it) and more customizable(markdown).
If you use the _url suffix, the generated URL is absolute. Use _path to get a relative URL.
<%= link_to "Home", root_url %>
<%= link_to "Home", root_path %>
also look at plugin: http://www.simonecarletti.com/blog/2009/10/actionmailer-and-host-value/

What is the meaning of <%- %> tags in html?

Okay I've been searching for this one and found a possible duplicate here (what does " <%: " do?). However this question adresses <%= and <%:, but not <%-.
So just to be sure I'm still asking my question.
I'm trying to setup a node.js/express/d3 application rendered on the server side. I found a repo describing what I want to do here:
https://github.com/gregjopa/d3-server-side-demo/blob/master/index.html
In that html code there is a snippet that I'd like to actually convert in jade:
<h1>D3 Server-side Demo</h1>
<%-
barChartHelper.getBarChart({
data: fixtureData,
width: 400,
height: 300,
xAxisLabel: '2012',
yAxisLabel: 'Views',
containerId: 'bar-chart-small'
})
%>
So I have two questions:
1)What is the meaning of the <%- %> in html?
And
2) How do I write this in jade?
Thanks,
The codebase you linked has EmbeddedJS as a dependency. EJS is a templating library which allows for using those tags.
Unescaped buffering with <%- code %>
So basically: These are not HTML tags, just tags belonging to a different templating language that allow inline JS code to be executed
You can use the same in Jade as explained in the docs
Unescaped Buffered Code
Unescaped buffered code starts with != and outputs the result of evaluating the JavaScript expression in the template.

Meteor {{#markdown}}

I am making a forum with markdown support.
I've been using meteor's markdown parser {{#markdown}} and have found something disturbing that I can't seem to figure out.
I am using {{#markdown}}{{content}}{{/markdown}} to render the content inserted into database.
The disturbing thing, for example, if someone writes up html without inserting it into the code block in the content...
example
<div class = "col-md-12">
Content Here
</div>
This will render as a column. They could also make buttons and etc through writing the HTML for it.
How to disable this behaviour so that when HTML is written it will not render into HTML but just simply show it as text?
You can write global helper, which will strip all html tags:
function stripHTML(string){
s = string.replace(/(<([^>]+)>)/ig, '');
return s;
}
Template.registerHelper('stripHTML', stripHTML)
Usage :
{{#markdown}}{{stripHTML content}}{{/markdown}}
Test it in console:
stripHTML("<div>Inside dive</div> Text outside")

Displaying some HTML code in my Rails view

In my controller, I'm outputting some HTML that I want to give to the user to copy but not have that HTML render what it actually renders on the page.
Here's the code from my show action:
#url = <iframe src=#{url} scrolling=\"no\" frameborder=\"0\" style=\"border:none; overflow:hidden;width:800px; height:21px;\" allowtransparency=\"true\" ></iframe>
What should I do differently so the view will display the HTML properly, the user can just copy the whole thing, paste it and be good to go?
You need to escape your HTML, and you can use html_escape() or aliased method h() to do this. In your view, where you currently have something like:
<%= #url %>
change to:
<%=h #url %>
For further info: http://api.rubyonrails.org/classes/ERB/Util.html#method-c-html_escape
in your view try this:
<%=raw(#url)%>
some usefull information can be found here:
http://www.tigraine.at/2012/08/23/when-to-use-raw-and-when-to-use-html_safe