How to include html coming from wysihtml5 in a view? - ruby-on-rails

I have text content prepared using the wysihtml5 gem, which I would like to show in a div. Question is how to "render" this text content, as to be "safe". Should I use
= text.html_safe
or
= simple_format(text)
or
= raw(text)
or...

If you would like to show everything, as it was entered in wysihtml5 (but not 100% safe), than use any of these:
= text.html_safe
= raw text
== text
If you would like to make it absolutely safe, then use:
== sanitize text, tags: %w(em strong b i u a ...), attributes: %w(href title ...)
In such way you can control tags that are allowed and allowed attributes for tags.

Related

Display body content as title when Title not present

I am currently working on a web application using Ruby on Rails and wanted to know how I would go about displaying the body contents as the title dynamically if there is no title present? I have validations to only allow titles to be up to 20 characters so I would like to only have it display the first 20 characters of the body as the title should not be present. I'm mostly trying to understand how I would accomplish this would it be by implementing a partial view or utilizing a or statement between how I would be passing in the title?
A very simple approach would be:
<%= instance.title.presence || truncate(instance.body, length: 20) %>
Note that you have to replace instance with your variable name. When this is used in more than one place then you might want to consider a different approach, like a helper method or a method defined on the model.
Read about Object#presence and the helper method truncate.

Rendering ERB in models: "no implicit conversion of ERB into String"

I am rendering an ASCII map that looks like the following:.
I want the asterisk in the map, which represents a character, to be red. Right now this characters asterisk is being assigned to its location as follows:
def mark_character_coordinates
WORLD.terrain[#character.y_coordinate][#character.x_coordinate][0][0] = "*"
end
I want my characters location on the map (the asterisk) to render as red. My idea is to try to wrap the asterisk in a span and give it an id. Then go into my CSS and make ID color red. My problem is I am not sure how to insert ERB into the model and have it render as such in the view. After reading similar problems on stackoverflow, this is the closest I got:
def mark_character_coordinates
WORLD.terrain[#character.y_coordinate][#character.x_coordinate][0][0]
= ERB.new("<span>*</span>")
end
What should I do? How do I insert ERB into a variable in the model and have it render accordingly in the view?
The best and easiest way to do this is to use JQuery. First, put the ASCII map inside a div with id="ascii-map" in your template. Then switch to the front-end. Once the DOM is fully loaded, you can parse the ASCII map, look for the asterisk, and then wrap it in a span element that has red color defined for its font.
In your CSS:
.red-font {
color: red;
}
Then, some JQuery:
$(document).ready(function() {
var text = $('#ascii-map').html();
var textWithRed = text.replace("*", "<span class='red-font'>*</span>");
$('#ascii-map').html(textWithRed);
});
I test this and confirmed that it works.
Well... you're breaking MVC pretty badly, so that's one thing. Other than that though, do you need ERB for this? You're not embedding ruby at all. Why not just have it as a string?
i.e
def mark_character_coordinates
WORLD.terrain[#character.y_coordinate][#character.x_coordinate][0][0] = "<span>*</span>"
end

Rails 4: Disable automatic CSS sanitizing when using built-in HTML sanitize

I'm building an application that has a HTML GUI interface to create, move and edit boxes (div) inside a container div. These boxes get assigned inline styles when editing, these inline styles are saved to the database and are output in the views:
<%= sanitize raw(#slide.content) %>
I want to sanitize the HTML itself, to avoid someone hacking in, for instance, a script tag, through sending that by editing what's sent to the server when the boxes are saved.
Rails 4 has a helper method sanitize available through the class ActionView::Helpers::SanitizeHelper. When I use this with a test content value that contains a malicious <script> tag, the script gets removed just fine. But sanitizing the content also strips CSS properties inside the style tag that are necessary for the boxes, like top, left, position, etc.
In the linked documentation, it's stated that sanitize will automatically use the function sanitize_css when it comes across a style attribute:
sanitize_css(style)
Sanitizes a block of CSS code. Used by sanitize when it comes across a style attribute.
I do not want this behaviour of sanitize. How can I disable sanitize using sanitize_css, to sanitize the HTML, but not the CSS?
You can allow any attributes and tags you need, so rails will skip them.
sanitize raw(#slide.content), tags: %w(table tr td ul li), attributes: %w(style href title)
Speaking about CSS rules themselves, it's a bit harder to allow additional rules, but still possible. You can monkey patch the HTML::WhiteListSanitizer class (https://github.com/rails/rails/blob/c71c8a962353642ee44b5cc6ed68dc18322eea72/actionpack/lib/action_view/vendor/html-scanner/html/sanitizer.rb). There are several attributes that can help.
In your config/application.rb file:
config.action_view.sanitized_allowed_tags = nil
config.action_view.sanitized_allowed_attributes = nil
safe lists found here: loofah html5 safelist

How to Display Brackets Correctly in Code in User Comments?

When a user posts a comment on my site, I run it through a sanitized markdown formatter on the backend and then display it on the site.
However, this causes the less-than and greater-than signs (< and >) to come out with their HTML codes (< and &rt;) inside the user's code examples (which gets marked with <pre> and <code> tags). The brackets display correctly outside of code, but how do I fix it so they show up correctly inside code?
In short, I want what now shows up as:
if(a < b)
To show up as:
if(a < b)
This is my code in the helper for marking down the user's comment:
def comment_markdown(text)
renderer = Redcarpet::Render::HTML.new()
markdown = Redcarpet::Markdown.new(renderer)
safe_text = sanitize text, tags: %w(b i code pre br p)
markdown.render(safe_text).html_safe
end
It's called in the view:
<%= comment_markdown comment.text %>
Rails already HTML-safe's text for display in views; so with your call to .html_safe in the comment_markdown method, it's getting escaped twice.
Simply remove your call to .html_safe:
def comment_markdown(text)
renderer = Redcarpet::Render::HTML.new()
markdown = Redcarpet::Markdown.new(renderer)
safe_text = sanitize text, tags: %w(b i code pre br p)
markdown.render(safe_text)
end
I think I'll just use Redcarpet's filter_html: true option to prevent any security issues from iframes and the like. Then I don't need to sanitize the text, so it doesn't escape text inside pre tags, and it displays normally. I just need to see how to configure it so users can't use distracting things like Headers.

Rails only escape certain sections of content

I'm looking to turn all words preceeded by a # (ie #stackoverflow) into a link that when clicked through will link to the search page with the word as a query.
I tried this recently and got the right HTML being returned, but because content is automatically escaped it showed as:
This is some content something
My question is: Is there any way to only apply html_safe to every part of the content except for these links?
If your tags are simple alphanumeric strings (i.e. nothing that needs to be HTML or URL encoded), then you could do something like this:
s = ERB::Util.html_escape(text_to_be_linkified).gsub(/#(\w+)/, '\1').html_safe
Then s.html_safe? will be true and <%= ... %> will pass the result through as-is. If you put this in a view helper, then you shouldn't need the ERB::Util. prefix on html_escape. If you do need to worry about URL or HTML encoding then you could modify the gsub replacement string appropriately.
For example:
> s = ERB::Util.html_escape('<pancakes & #things').gsub(/#(\w+)/, '\1').html_safe
> puts s.html_safe?
true
> puts s
<pancakes & things

Resources