I have a Portfolio model that contains a comments field of type text, whose values are a set of paragraphs delimited by some combo of cr and nl characters. The objective is to extract the paragraphs into an array, wrap them in <p> tags, and rejoin them for output to the browser; so the focus in the code below is lines 6-8.
The problem I'm having is that the < and > characters are getting rendered as HTML entities < and >.
I'm new to Ruby and Rails, so my guess is that the reason this isn't working as intended is because I'm probably taking an incorrect approach--and I'd like to know how an experienced Ruby coder would address this sort of situation. How do you insert HTML tags into content before you send it to a view? Or is that always a violation of the MVC model--in which case, what's a correct way to solve this sort of problem?
Here's the code:
1. module ApplicationHelper
2.
3. def portfolio_featured
4. #portfolios = Portfolio.all
5. #portfolios.each do |p|
6. paras = p.comments.split(/\r?\n\r?\n/)
7. paras.collect! { |p| "<p>" + p + "</p>" }
8. p.comments = paras.join
9. end
10. end
11.
12. end
take a look at simple_format TextHelper.
It is probably what you are looking for.
You can use TextHelper#simple_format or something fancy like Bluecloth (Markdown), but if you want to cook it yourself, that's what you can write (the key is using safe_join):
def portfolio_featured
safe_join(Portfolio.all.map do |portfolio|
portfolio.comments.lines.map { |line| content_tag(:p, line.chomp) }
end)
end
Related
So, I'm working on an html parser to extract some text data from a list of and format it before giving an output. I have a title that I need to set as bold, and a description which I'll leave as it is. I've found myself stuck when I reached this situation:
<div class ="Content">
<Strong>Title:</strong>
description
</div>
As you can see the strings are actually already formatted but I can't seem to find a way to get the tags and the text out together.
What my script does kinda looks like:
article = "" #this is where I normally store all the formatted text, it's necessary that I get all the formatted text as one loooong string before I Output
temp1=""
temp2""
result = soup.findAll("div", {"class": "Content"})
if(result!=none):
x=0
for(i in result.find("strong")):
if(x==0):
temp1 = "<strong>" + i.text + "</strong>"
article += temp1
x=1
else:
temp2 = i.nextSibling #I know this is wrong
article += temp2
x = 0
print(article)
It actually throws an AttributeError but it's a wrong one since the output is "Did you call find_all() when you meant to call find()?".
I also know I can't just use .nextSibling like that and I'm litterally losing it over something that looks so simple to solve...
what I need to get is: "Title: description"
Thanks in advance for any response.
I'm sorry if I couldn't explain really well what I'm trying to accomplish but that's kind of articulated; I actually need the data to generate a POST request to a CKEditor session so that it adds the text to the html page, but I need the text to be formatted in a certain way before uploading it. In this case I would need to get the element inside the tags and format it in a certain way, then do the same with the description and print them one after the other, for example a request could look like:
http://server/upload.php?desc=<ul>%0D%0A%09<li><strong>Title%26nbsp%3B<%2strong>description<%2li><%2ul>
So that the result is:
Title1: description
So what I need to do is to differentiate between the element inside the tag and the one out of it using the tag itself as a refernce
EDIT
To select the <strong> use:
soup.select_one('div.Content strong')
and then to select its nextSibling:
strong.nextSibling
you my need to strip it to get rid of whitespaces, ....:
strong.nextSibling.strip()
Just in case
You can use ANSI escape sequences to print something bold, ... but I am not sure, why you would do that. That is something should be improved in your question.
Example
from bs4 import BeautifulSoup
html='''
<div class ="Content">
<Strong>Title:</strong>
description
</div>
'''
soup = BeautifulSoup(html,'html.parser')
text = soup.find('div', {'class': 'Content'}).get_text(strip=True).split(':')
print('\033[1m'+text[0]+': \033[0m'+ text[1])
Output
Title: description
You may want to use htql for this. Example:
text="""<div class ="Content">
<Strong>Title:</strong>
description
</div>"""
import htql
ret = htql.query(text, "<div>{ col1=<strong>:tx; col2=<strong>:xx &trim }")
# ret=[('Title:', 'description')]
I end up seeing a number 5 after I display a font awesome-icon. I am using HAML.
The HAML code in index.html.haml file:
{.container.service_providers
.row
.small-10.columns
-#categories.each do |category|
.button.tiny
=category.name
=if category.name == "Academic Enrichment"
-"Academic Enrichment"
#{fa_icon 'puzzle-piece'}
=if category.name == 'Academic Support'
#{fa_icon 'calculator'}
The categories are being raked from the CSV file:
Also, when you inspect element you see the 5 in displayed in the html document but not on the haml page.
Change the = if for - if, that is the equals for a minus.
In Haml, using = means you want to print that output to the buffer, and - just runs the ruby code without printing the result to the buffer.
You're probably seeing the 5 as a result of the comparison.
Search the CSV file for a "5", inspect to see that it's formatted correctly around every found5 ... no missing commas, brackets or quotes etc.
set tabstop=4
set shiftwidth=4
set nu
set ai
syntax on
filetype plugin indent on
I tried this, content.gsub("\r\n","<br/>") but when I click the view/show button to see the contents of these line, I get the output/result=>
set tabstop=4<br/> set shiftwidth=4<br/> set nu<br/> set ai<br/> syntax on<br/> filetype plugin indent on
But I tried to get those lines as a seperate lines. But all become as a single line. Why?
How can I make all those lines with a html break (<br/>) ?
I tried this, that didn't work.
#addpost = Post.new params[:data]
#temptest = #addpost.content.html_safe
#addpost.content = #temptest
#logger.debug(#addpost)
#addpost.save
Also tried without saving into database. Tried only in view layer,<%= t.content.html_safe %> That didn't work too.
Got this from page source
vimrc file <br/>
2011-12-06<br/><br/>
set tabstop=4<br/><br/>set shiftwidth=4<br/><br/>set nu<br/><br/>set ai<br/><br/>syntax on<br/><br/>filetype plugin indent on<br/>
Edit
Delete
<br/><br/>
An alternative to convert every new lines to html tags <br> would be to use css to display the content as it was given :
.wrapped-text {
white-space: pre-wrap;
}
This will wrap the content on a new line, without altering its current form.
You need to use html_safe if you want to render embedded HTML:
<%= #the_string.html_safe %>
If it might be nil, raw(#the_string) won't throw an exception. I'm a bit ambivalent about raw; I almost never try to display a string that might be nil.
With Ruby On Rails 4.0.1 comes the simple_format from TextHelper. It will handle more tags than the OP requested, but will filter malicious tags from the content (sanitize).
simple_format(t.content)
Reference : http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html
http://www.ruby-doc.org/core-1.9.3/String.html
as it says there gsub expects regex and replacement
since "\n\r" is a string you can see in the docs:
if given as a String, any regular expression metacharacters it contains will be interpreted literally, e.g. '\d' will match a backlash followed by ādā, instead of a digit.
so you are trying to match "\n\r", you probably want a character class containing \n or \r -[\n\r]
a = <<-EOL
set tabstop=4
set shiftwidth=4
set nu
set ai
syntax on
filetype plugin indent on
EOL
print a.gsub(/[\n\r]/,"<br/>\n");
I'm not sure I exactly follow the question - are you seeing the output as e.g. preformatted text, or does the source HTML have those tags? If the source HTML has those tags, they should appear on new lines, even if they aren't on line breaks in the source, right?
Anyway, I'm guessing you're dealing with automatic string escaping. Check out this other Stack Overflow question
Also, this: Katz talking about this feature
I have a helper method for my Rails app that returns a string with HTML code for a Google Groups subscription form. Unfortunately, it comes out on the page like plain text. How can I force it to render as HTML?
Thanks in advance.
The result of your helper needs to be marked as "html_safe" in Rails 3. Otherwise, the tags will be escaped.
def my_helper
data = "<p>Hello!</p>"
data.html_safe
end
I suppose it was a problem with Rails html sanitize.
from rails changelog
You no longer need to call h(string)
to escape HTML output, it is on by
default in all view templates. If you
want the unescaped string, call
raw(string).
try it
One thing to watch out for is when joining multiple strings like this
def custom_check_box(checked)
'<span class="my-custom-checkbox '+( checked ? 'checked' : '')+'"></span>'.html_safe
end
In this case, only the last part is marked as html safe. Make sure you get the whole thing.
def custom_check_box(checked)
('<span class="my-custom-checkbox '+( checked ? 'checked' : '')+'"></span>').html_safe
end
i have an HTML, that should be transformed, having some tags replaced with another tags.
I don't know about these tags, because they will come from db. So, set_attribute or name methods of Nokogiri are not suitable for me.
I need to do it, in a way, like in this pseudo-code:
def preprocess_content
doc = Nokogiri::HTML( self.content )
doc.css("div.to-replace").each do |div|
# "get_html_text" will obtain HTML from db. It can be anything, even another tags, tag groups etc.
div.replace self.get_html_text
end
self.content = doc.css("body").first.inner_html
end
I found Nokogiri::XML::Node::replace method. I think, it is the right direction.
This method expects some node_or_tags parameter.
Which method should i use to create a new Node from text and replace the current one with it?
Like that:
doc.css("div.to-replace").each do |div|
new_node = doc.create_element "span"
new_node.inner_html = self.get_html_text
div.replace new_node
end