Rendering markdown with Slim/Rails from an instance var - ruby-on-rails

I'm having trouble getting Slim to render my markdown:
div.container
div.row
div.col-md-8.job_description
markdown:
= #listing.job_description
That just renders the string
This is an h1 ## h2 ### h3 > this is a quote * hello * goodbye foo
No line breaks or anything (which are contained in the actual string)
How do I get this to render properly? Thanks!

I gave up on using markdown: in slim, had tried everything.
I ended up creating this helper, place it in just any file in app/helpers
def markdown(content)
return '' if content.blank?
markdown = Redcarpet::Markdown.new(Redcarpet::Render::XHTML, autolink: true, space_after_headers: true)
sanitize(markdown.render(content)).html_safe
end
And then in a view
= markdown #listing.job_description
You will of course have to install the redcarpet gem.
gem 'redcarpet'

Rendering Markdown out of a variable in this way isn't possible, as Slim first renders the Markdown (or any other embedded engine language) and only after that interpolates the variable contents.
It makes sense that it would work this way as Slim's embedded engine tags are intended as a way of including different languages in-line so you can read them there. If the markdown isn't included in literal form in the template, there's no advantage to using the embedded engine over simply rendering the Markdown before you pass it to Slim (as HTML, and using '==' to prevent further processing by Slim).
I think, also, that it's set up like this because it's intended to provide and easy way for interpolating text into Markdown - which doesn't itself have a means of interpolation - within the same template as everything else.
The helper Iceman suggests is a nice way to do it. I'd probably call it outside of the template, but that's just because it's my personal preference to do as little as possible inside the template.

Looks like your markdown content is not indented under markdown:, so it won't be processed by markdown.
It should look more like this:
div.col-md-8.job_description
markdown:
= #listing.job_description
See this section of the docs for more information.

Related

rails 5.x: add nofollow to all links in 'sanitize'

I am working on a Rails application whose HAML templates frequently make use of a routine called sanitize. I have deduced from context that this routine sanitizes user-controlled HTML. Example:
# views/feed_items/_about.html.haml
%h3 Summary:
.description
= sanitize #feed_item.description
I want to make this routine add 'rel=nofollow' to all outbound links, in addition to what it's already doing. What is the most straightforward way to do that?
N.B. I am not having any luck finding the definition of this method, or the official configuration knobs for it. The vendor directory has two different HTML sanitizer gems in it and I can't even figure out which one is being used. This is a large, complicated web application that I did not write, and I barely understand Ruby, let alone all of Rails' extensions to it. Please assume I do not know any of the things that you think are obvious.
The sanitizer will strip out the rel tags if they exist.
I ran into a similar issue and added an additional helper method - clean_links to the ApplicationHelper module, and called it after sanitizing the content.
# application_helper.rb
def clean_links html
html.gsub!(/\\2')
html.html_safe
end
This method looks for all <a> tags, and adds rel="nofollow". The html_safe method is necessary or else the HTML will be displayed as a string (it's already been sanitized).
This solution treats all links equally, so if you only want this for links pointing outside the domain, you'll have to update the REGEX accordingly.
In your view: <%= clean_links sanitize(#something) %>
So, first the content is sanitized, then you add the rel="nofollow" tag before displaying the link.
Actually there's a built-in way:
sanitize "your input", scrubber: Loofah::Scrubbers::NoFollow.new

How to use slim for mailer text template

I am using slim as the template engine for my rails app and would like to use slim for mailer templates as well.
There is no problem with html mailer templates (views/mailer/default_email.en.html.slim) but, I am not sure how to make the text templates work.
I have placed a text template in views/mailer/default_email.en.text.slim with this content:
Hello,
Your video is ready.
= #url
Thank you,
The A-Team
But the result is parsed as slim HTML, and looks like this:
<Hello>,</Hello><Your>video is ready.</Your><Click>the link below to watch it:</Click>http://watch.thy/video<Thank>you,</Thank><The>A-Team</The>
Other than prefixing every line with a pipe, isnt there a more natural way?
I even looked for an embedded plugin (like the markdown one) to say "plain text" but there is none.
Thanks in advance.
Slim was designed to generate HTML, not plain text, so you'll have to either use the pipe prefix for each line or go with .text.erb templates. I'd use the ERB templates, especially if you don't have a lot of interpolation going on.
For what it's worth, you can actually go the Slim route without having to prefix each line with a pipe, like so:
|
Hello,
<br><br>
Your video is ready.<br>
#{#url}
<br><br>
Thank you,<br>
The A-Team
I would definitely agree with eugen though, that the text.erb route is the best fit. Just providing another solution, in case somebody absolutely insisted on doing this in Slim. :-)

Rails - Mix erb tags with markdown

I want the users on my blogsite to be able to type in markdown text in a textarea to make a blogpost. This markdown text would then be converted with a tool like Redcarpet or kramdown. Now I also want the user to be able to call a partial view that lays out some pictures. So in other words, I want the user to be able to type in the following code anywhere in between his markdown text (and it being interpreted as erb code)
<%= render partial: "slider", locals: {imgs: ["image1.jpg", "image2.jpg"]} %>
Is this possible somehow? kramdown allows you to use block-level HTML tags (div, p, pre, …), so maybe this could be used to some advantage?
Do you really want your customers to be able to write ERB? That's extremely dangerous, they can use any Ruby function in ERB, including Kernel functionalities. What about allowing a simple templating system, either a custom one or an existing one. For example you can use Liquid (from Shopify), provide some custom tags so they won't need all the boilerplate but just something like {% dosomething 'partial', 'img1', 'img2' %}, then you first convert liquid into normal text, then you convert markdown to html, cache it and display that to the user. An example:
# get your customer text from somewhere, like params[:markdown_text]
template = params[:markdown_text]
markdown = Liquid::Template.parse(template).render
html_text = Redcarpet::Markdown.new(renderer, extensions = {}).render(markdown)
puts html_text.to_s # => text with html tags, ensure to use `html_safe` on it in views
And you have your text ready

Pass multiline html string(markdown text) from rails to javascript

I have a markdown text saved in the databse and I want to show it as html to the user. I am using markdown.js as the processor and I pass the big multiline html string from rails to javascript by rendering a js.erb file from the controller.
But since it is multiline, the javascript becomes invalid. Is there any rails function which will take the whole string and assign it as a single line string to javascript variable. I cannot use html_safe also as some things might be escaped. What is the best way to handle markdown?
sample markdown
![enter image description here](https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRiOb7-0qeyx73XuXNqzLpxgXTlf5UMrMnF5zm-UKn3wLaXCW0UUw "enter image title here")
Hello
If you render erb server-side anyway, you will probably be better rendering Markdown server-side as well. You can use Redcarpet for that.
Add gem redcarpet to your Gemfile.
Run bundle install
Use it:
text = "my _markdown_ *variable*"
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML)
markdown.render(text)
It will be a good idea to save rendered HTML in the database, to save CPU time on re-rendering the same text every time you want to show it to client. So you can add something like this to your model:
class Article
# let's say that model has 'source' attributes with Markdown
# and we want to put resulting HTML into 'html' attribute
before_save :markdown
def markdown
self.html = Redcarpet::Markdown.new(Redcarpet::Render::HTML).render(source)
end
end

Generating a link with Markdown (BlueCloth) that opens in a new window

I'd like to have a link generated with BlueCloth that opens in a new window. All I could find was the ordinary [Google](http://www.google.com/) syntax but nothing with a new window.
Ideas?
Regards
Tom
Here is a complete reference for markdown: http://daringfireball.net/projects/markdown/syntax
And since there is no mention of how to set the target attribute, I would believe it is not directly possible, but the reference also says:
For any markup that is not covered by
Markdown’s syntax, you simply use HTML
itself. There’s no need to preface it
or delimit it to indicate that you’re
switching from Markdown to HTML; you
just use the tags.
Source: http://daringfireball.net/projects/markdown/syntax#html
So I would suggest you have to use the html syntax for links like this
update
if you wrap the markdown generated content in a div with a specific id like this:
and you use jQuery, you can add the following javascript:
$('#some_id a').attr('target','_blank');
Or you can save the BlueCloth output in a variable before outputting.
markdown_generated_string.gsub!(/<a\s+/i,'<a target="_blank" ')

Resources