Possible to embed markdown within erb? - ruby-on-rails

If you use haml as rails view template, you can write portion of your page using markdown by using the ":markdown" filter.
Is is possible to do the same using erb?

It's pretty easy to write a method that does it, assuming you're using something like Rails which has #capture, #concat, and #markdown helpers. Here's an example, using Maruku:
def markdown_filter(&block)
concat(markdown(capture(&block)))
end
Then you can use this as so:
<% markdown_filter do %>
# Title
This is a *paragraph*.
This is **another paragraph**.
<% end %>
There are a few things to note here. First, it's important that all the text in the block have no indentation; you could get around this by figuring out the common indentation of the lines and removing it, but I didn't do that in the example helper above. Second, it uses Rails' #markdown helper, which could easily be implemented in other frameworks as so (replacing Maruku with your Markdown processor of choice):
def markdown(text)
Maruku.new(text).to_html
end
Rails 3 has removed the #markdown helper, so just add the above code in the appropriate helper, substituting the Markdown processor of your choice.

ERB does not have filtering like this built-in. You'll need to directly use a gem that handles it, like RDiscount or the venerable BlueCloth.

Related

Is there a helper for creating handlebars blocks in haml?

Because handlebars tags are evaluated after haml is compiled to html, and handlebars counts as plane text in haml you cannot indent logic
{{#if misc}}
%b Misc Products
Total:
{{misc_total}}
{{#each misc}}
{{price_charged}}
{{notes}}
{{/each}}
{{/if}}
Which is hard to read.
I made a rails helper to make this better looking*.
def handlebars_helper(helper, &block)
raise ArgumentError, "Missing block" unless block_given?
open = ActiveSupport::SafeBuffer.new("{{##{helper}}}") # helper opening
open.safe_concat capture(&block)
open.safe_concat("{{/#{helper.split.first}}}") # helper closing
concat(open)
end
which lets you write haml that looks like this
- handlebars_helper 'if misc' do
%b Misc Products
Total:
{{misc_total}}
- handlebars_helper 'each misc' do
{{price_charged}}
{{notes}}
Has this been done before, or is there a better way for me to do it?
*this helper looks a bit messy, I'm not that comfortable with blocks how would I clean this up?
If you want to use HAML to generate handlebars code, you can use hamlbars, which will provide you a few helpers to help facilitate indentation. Unfortunately you'll still be stuck with awkward indentation surrounding if/else.
I'd recommend Emblem.js as an alternative... the syntax is closer to Slim than HAML, but there's gonna be no ugly helper code polluting your templates just to preserve indentation. Disclaimer: I wrote emblem.

In Rails, how to write a helper function "who_am_i" so that a view or partial can use it to report which file it is?

When designing for layout and styling with CSS, it might be useful to add a line in the view or partial:
<%= who_am_i %>
or if using haml:
= who_am_i
so that it will print on the webpage
this is view/products/_footer.html.haml
How can this helper be written? (or is there one already in Rails?)
(my first try was to use __FILE__ and do some manipulation with string, and it works well if everything is done inside the view or partial file, but when it moves to helper, then __FILE__ becomes helpers/application_helper.rb so it won't work. But I'd like to find out possibly better ways to do it)
Your helper method should be:
def who_am_i
#template.template
end
Rails 3
def who_am_i
#_virtual_path
end
Note:
I tested the solution in Rails 3.0.5 and it works. I am not certain that it will work in all scenarios. Use with caution.

generate nofollow links in RDiscount output

My rails app is using RDiscount to generate HTML from user-supplied markdown text, and I noticed that the anchor tags don't have rel="nofollow". This is a big issue for me as my app is open to the public. Is there a way to enable nofollow links, or are there better solutions?
Thanks!
I think this is possible only with Kramdown, which is a ruby Markdown parser with extended syntax. You would do that then as shown in the link:
[link](test.html){:rel='nofollow'}
In the mean time, I am using this hack, by re-parsing the RDiscount output and add a rel="nofollow" to each anchor:
def markdown(input)
html = RDiscount.new(input).to_html
doc = Nokogiri::HTML::DocumentFragment.parse(html)
doc.css("a").each do |link|
link['rel'] = 'nofollow'
end
doc.to_html
end
Though I think this should really be handled by the markdown parser.
I needed to do something similar, add target="_new" to all links. Solved it using Kramdown and a custom Kramdown::Converter::Html class.
Define a Kramdown::Converter::Html subclass (kramdown/converter/my_html.rb in some autoload path)
class Kramdown::Converter::MyHtml < Kramdown::Converter::Html
def convert_a(el, indent)
el.attr['target'] = '_new'
super
end
end
I also have a view helper in app/helpers/application_helper.rb
def markdown(str)
Kramdown::Converter::MyHtml.convert(Kramdown::Document.new(str).root)[0].html_safe
end
Ideally it should be possible to just use Kramdown::Document.new(str).to_my_html.html_safe but I can't get it to work in rails development mode as Kramdown uses const_defined? to see if a converter is available and that does not trigger the autoloader. Please comment if you know how to fix this.
There is an open feature request on RDiscount to support modifying links in this fashion.
It is scheduled for one of the upcoming RDiscount 2.1.5.x releases.

BlueCloth isn't working with Rails 3

Is BlueCloth compatible with Rails 3? I can't make it work, maybe someone uses it?
There is supposed to be a helper called 'markdown' available in the views after requiring 'bluecloth', but this doesn't seem to be available.
I'm upgrading an app to rails3 right now and it worked fine for me. I use a helper function called "format" in templates though the code below also provides a markdown function (in rails3 you'll have to use that with raw()). Here's the contents of my [project]/app/helpers/application_helper.rb
module ApplicationHelper
# Format text for display.
def format(text)
sanitize(markdown(text))
end
# Process text with Markdown.
def markdown(text)
BlueCloth::new(text).to_html
end
end
Like a previous poster said, you'll also need
gem 'bluecloth'
in your [project]/Gemfile. My template looks like:
<p><%= format #post.body %></p>
With the markdown function it would be:
<p><%= raw(markdown(#post.body)) %></p>
So I use the format function. Rename the functions however you want.
I've created a fresh Rails 3 app and in the Gemfile I added:
gem 'bluecloth', '>= 2.0.0'
Then opened the console:
ruby-1.8.7-p302 > BlueCloth.new('**hello**').to_html
=> "<p><strong>hello</strong></p>"
So it appears to be working, at least for me.
You could also try Rdiscount which I am not shure but I think is based on the same C library, or at least has similar benchmarks.
You should be more specific in how is it not working: Does it raises an error? Doesn't it renders html? etc...
What you could do, not saying it is pretty, is creating an initializer in your rails project and put the following in it:
require 'bluecloth'
class String
def markdown
BlueCloth.new(self).to_html
end
end
This should enable the markdown method on every string object.
I'd suggest switching to RDiscount over BlueCloth. It's a drop in replacement and is better on all counts.
http://github.com/rtomayko/rdiscount

Issue with Haml files

Hi i converting rails views from erb to Haml .The issue i faced is when use the form_for the haml throws the UNEXPECTED $end error. I am sure i did the space indentation well with in form_for .......Even if i use "each do" loop is says the same error. if i revert the haml to erb it works fine.
Rails version i used : 2.3.2 & i installed haml gem 2.2.19 as well as haml plugin also.
my controller code :
def new
#user = User.new
end
My View code :
.contentContainer.signup
- form_for(#user) do |f|
Make sure your haml indentation is perfect.
.contentContainer.signup
- form_for(#user) do |f|
= f.text_field :name
Are you including - end in your templates? Haml takes care of ends for you, so if you add your own, it won't work.
Can you paste your entire template (in a code block, so it's formatted properly)?
There's also a good command-line tool to make transition easier: html2haml. It doesn't always produce the prettiest haml, but it certainly works.
Hey, there's even a web-based form for this: http://html2haml.heroku.com/
Generally, be sure your indentation is perfect. haml is very particular about indentation. If you use a decent editor (such as textmate or vim) this is an easy task.
If the last line in file is indented there has to be an addidtional, empty line.

Resources