Archive for November, 2008

Install markItUp! in Ruby on Rails

Saturday, November 8th, 2008

If you’re torn between a WYSIWYG editor and something clean like Textile/Redcloth, then markItUp! will provide you with some nice middle ground. The tool is well documented, but there are a few “notes” for installing it in Rails that aren’t in the docs.

1. Initial setup

Since there’s overhead associated with markItUp!, I set a variable @content_submission to true so that my standard layout template can skip all of the extra javascript when it’s not necessary. To keep things simple, I’m going to follow the markItUp! hierarchy, which means it’s stylesheets will be in your javascripts path.

  1. <%- unless @content_submission.nil? -%>
  2. <%= javascript_include_tag "jquery-1.2.6.min" %>
  3. <%= javascript_include_tag "markitup/jquery.markitup" %>
  4. <%= javascript_include_tag "markitup/sets/textile/set" %>
  5. <link rel="stylesheet" type="text/css" href="/javascripts/markitup/skins/markitup/style.css" />
  6. <link rel="stylesheet" type="text/css" href="/javascripts/markitup/sets/textile/style.css" />
  7. <%- end -%>

Install jQuery into your javascripts folder along with markItUp!. Download whatever markItUp! set you want to use (I’m using textile above, which assumes you’ve already ran sudo gem install redcloth) and drop that in the sets folder. All of this is documented in the standard markItUp! docs.

You only need to make one edit to the standard markItUp! file. In jquery.markitup.js, edit previewTemplatePath to the following:

  1. previewTemplatePath: '/javascripts/markitup/templates/preview.html'

2. Add an action to parse the text

I’ve got a controller called content_controller that will handle my Textile processing with Redcloth. I’ve defined an action as follows:

  1. def parse_textile
  2.   render :text => RedCloth.new(params[:data]).to_html
  3. end

You may want to add more to this action to provide security.

3. Add a route to for your new action

Assuming you’re using RESTful routes, just modify your existing route:

  1. map.resources :content, :member => {:parse_textile => :post}

4. Tell markItUp! about your route

Lastly, edit your set file and tell it about the route:

  1. previewParserPath: '/content/parse_textile'

Ruby on Rails Diff Text to HTML <ins> and <del>

Tuesday, November 4th, 2008

This code is perfect if you have 2 text objects in your Rails application and you want to compare their differences in one of your HTML views. It’s 99% pure Ruby too, so if you alter the first line, you can use it for other purposes.

Only one thing to note: you must have diff installed. I’m using: diff (GNU diffutils) 2.8.1.

  1. #set up some variables to reference later
  2. temporary_directory = File.join(Rails.root, "tmp")
  3. max_lines = 9999999 #needs to be larger than the most lines you'll consider
  4. diff_header_length = 3
  5.  
  6. # text_old and text_new should be the values of the string objects to compare
  7. # these are just example strings to show it works
  8. text_old      = "line1\ndeleted line2\nline3\n\nline4\nline5"
  9. text_new      = "line1\ninserted line2\nline3\n\nline4\nline5"
  10.  
  11. # since we're using diff on the file system, we'll save the text we want to compare
  12. # and then run diff against the two files
  13. file_old_name = File.join(temporary_directory,"file_old"+rand(1000000).to_s)
  14. file_new_name = File.join(temporary_directory,"file_new"+rand(1000000).to_s)
  15. file_old      = File.new(file_old_name, "w+")
  16. file_new      = File.new(file_new_name, "w+")
  17. file_old.write(text_old+"\n")
  18. file_new.write(text_new+"\n")
  19. file_old.close
  20. file_new.close
  21.  
  22. # diff will give provide a string showing insertions and deletions.  We will
  23. # split this string out by newlines if there are difference, and mark it up
  24. # accordingly with html
  25. lines = %x(diff -­-­­­­­­unified=#{max_lines} #{file_old_name} #{file_new_name})
  26. if lines.empty?
  27.   lines = text_new.split(/\n/)
  28. else
  29.   lines = lines.split(/\n/)[diff_header_length..max_lines].
  30.   collect do |i|
  31.     if i.empty?  
  32.       ""
  33.     else
  34.       case i[0,1]
  35.       when "+"; then "<ins>"+i[1..i.length-1]+"</ins>"
  36.       when "-"; then "<del>"+i[1..i.length-1]+"</del>"
  37.       else; i[1..i.length-1]
  38.       end
  39.     end
  40.   end
  41. end
  42.  
  43. #clean up the temporary diff files we created
  44. File.delete(file_new_name)
  45. File.delete(file_old_name)
  46.  
  47. #return marked up text
  48. lines.join("\n")

If you fire up RAILS_ROOT/script/console and paste that code in, it will return a nicely marked up string like this:

  1. line1
  2. <del>deleted line2</del>
  3. <ins>inserted line2</ins>
  4. line3
  5.  
  6. line4
  7. line5

Use CSS to make your ins and del tags render however you like.