Markdown markup in a RubyOnRails application


    In one new project written in ruby ​​on rails, the task was set to enable the user to use markdown markup to format text. One implementation option is described in this article.

    This article does not describe the basics of ruby ​​on rails. I mean, the reader can create a project and run it in his favorite IDE / from the console / even like that. Plus, at the end of the article there is a link to the sources of the demo project.
    One clarification: I use haml for view sheks and twitter bootstrap for layout.
    Let's say we have an application. And we need to add the “Article” class to it with the header and content fields . The content field will be of type text. We need to apply markdown markup to it.

    Add our class and at the same time the controller and view-shki
    rails generate scaffold Post title content:text
    rake db:migrate
    



    Markdown parser


    As a parser we use redcarpet
    # Gemfile
    ...
    gem "redcarpet"
    

    Add helper to display text using markdown markup
    # app/helpers/application_helper.rb
    module ApplicationHelper
      def markdown(text)
        renderer = Redcarpet::Render::HTML.new(hard_wrap: true, filter_html: true)
        options = {
            autolink: true,
            no_intra_emphasis: true,
            fenced_code_blocks: true,
            lax_html_blocks: true,
            strikethrough: true,
            superscript: true,
            space_after_headers: true
        }
        Redcarpet::Markdown.new(renderer, options).render(text).html_safe
      end
    end
    

    Redcarpet :: Markdown is the markdown parser itself. Redcarpet :: Render :: HTML is one of the renderers. Specifically, this generates html from markdown markup. If you wish, you can write your own renderer or inherit from existing ones. Possible options for the renderer and parser can be found in the documentation .

    Use helper to display content
    -# app/views/posts/show.html.haml
    %h3= @post.title
    %p= markdown(@post.content)
    = link_to 'Edit', edit_post_path(@post)
    \|
    = link_to 'Back', posts_path
    

    Now if we create an article with the following content
    > this is quotes
    List:
    - item 1
    - item 2
    - item 3
    [this is link](http://example.com)
    ![image](http://placehold.it/350x150)
    ``` 
    class Cat < Animal 
      def say 
        "Meow!" 
      end 
    end 
    ```
    

    then we will see approximately the following picture




    Markdown Editor


    Add the visual editor MarkItUp to the project . You can use the markitup-rails gem for this.
    # Gemfile
    ...
    gem 'markitup-rails'
    

    # app/assets/javascripts/application.js
    …
    //= require markitup
    …

    // app/assets/stylesheets/application.css.scss
    …
    @import "markitup";
    @import "markitup-markdown";

    Finally, we apply the editor to our text field in the form of editing the article
    # app/assets/javascripts/posts.js.coffee
    jQuery ->
      markdownSettings = {
        previewParserPath: '/markdown/preview'
        onShiftEnter:	{keepDefault:false, openWith:'\n\n'}
        markupSet: [
          {
            name:'First Level Heading', key:'1',
            placeHolder:'Your title here...',
            closeWith: (markItUp) -> markdownTitle(markItUp, '=')
          },
          {
            name:'Second Level Heading', key:'2', placeHolder:'Your title here...',
            closeWith: (markItUp) -> markdownTitle(markItUp, '-')
          },
          {name:'Heading 3', key:'3', openWith:'### ', placeHolder:'Your title here...' }
          {name:'Heading 4', key:'4', openWith:'#### ', placeHolder:'Your title here...' }
          {name:'Heading 5', key:'5', openWith:'##### ', placeHolder:'Your title here...' }
          {name:'Heading 6', key:'6', openWith:'###### ', placeHolder:'Your title here...' }
          {separator:'---------------' }
          {name:'Bold', key:'B', openWith:'**', closeWith:'**'}
          {name:'Italic', key:'I', openWith:'_', closeWith:'_'}
          {separator:'---------------' }
          {name:'Bulleted List', openWith:'- ' }
          {name:'Numeric List', openWith: (markItUp) -> markItUp.line+'. ' }
          {separator:'---------------' }
          {
            name:'Picture', key:'P',
            replaceWith:'![[![Alternative text]!]]([![Url:!:http://]!] "[![Title]!]")'
          },
          {
            name:'Link', key:'L', openWith:'[',
            closeWith:']([![Url:!:http://]!] "[![Title]!]")',
            placeHolder:'Your text to link here...'
          },
          {separator:'---------------'}
          {name:'Quotes', openWith:'> '}
          {name:'Code Block / Code', openWith:'(!(\t|!|`)!)', closeWith:'(!(`)!)'}
          {separator:'---------------'}
          {name:'Preview', call:'preview', className:"preview"}
        ]
      }
      markdownTitle = (markItUp, char) ->
        heading = '';
        n = $.trim(markItUp.selection||markItUp.placeHolder).length;
        for i in [0..n]
          heading += char
        '\n'+heading
      $('#post_content').markItUp(markdownSettings)
    

    where post_content is the id of the text field. Editor settings (markdownSettings) are taken from the documentation .
    And now the edit form looks something like this




    Preview


    It is worth paying attention to one line
    # app/assets/javascripts/posts.js.coffee
    ...
    previewParserPath: '/markdown/preview'
    

    This is the path to the server page that will form the preview. We realize it
    # app/controllers/markdown_controller.rb
    class MarkdownController < ApplicationController
      def preview
        @text = params[:data]
      end
    end
    

    -# app/views/markdown/preview.html.haml
    = markdown(@text)

    # config/routes.rb
    ...
    post "markdown/preview"
    

    And now we have a working preview (with the above settings called by the last button on the editor panel)

    Useful links:

    Also popular now: