- PVSM.RU - https://www.pvsm.ru -

В одном новом проекте, написанном на ruby on rails, была поставлена задача дать возможность пользователю использовать markdown-разметку для форматирования текста. Один из вариантов реализации описан в данной статье.
Статья не описывает основы ruby on rails. Я подразумеваю, что читатель может создать проект и запустить его в своей любимой IDE / из консоли / еще как. Плюс в конце статьи есть ссылка на исходники демонстрационного проекта.
Одно уточнение: я использую haml [1] для view-шек и twitter bootstrap [2] для оформления.
Допустим что у нас есть приложение. И нам надо добавить в него класс «Статья» с полями заголовок и содержимое. Поле содержимое будет типа text. К нему то нам и необходимо применить markdown-разметку.
Добавим наш класс и заодно контроллер и view-шки
rails generate scaffold Post title content:text
rake db:migrate
В качестве парсера используем redcarpet [3]
# Gemfile
...
gem "redcarpet"
Добавляем helper для вывода текста с использованием markdown разметки
# 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 — сам markdown-парсер. Redcarpet::Render::HTML — один из рендереров. Конкретно этот генерирует html из markdown разметки. При желании можно написать свой рендерер или унаследовать от существующих. Возможные значения опций для рендерера и парсера можно посмотреть в документации [4].
Применяем helper для отображения содержимого
-# 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
Теперь если мы создадим статью со следующим содержимым
> this is quotes
List:
- item 1
- item 2
- item 3
[this is link](http://example.com)

```
class Cat < Animal
def say
"Meow!"
end
end
```
то увидим примерно следующую картину

Добавим в проект визуальный редактор MarkItUp [5]. Для этого можно использовать гем markitup-rails [6]
# Gemfile
...
gem 'markitup-rails'
# app/assets/javascripts/application.js
…
//= require markitup
…
// app/assets/stylesheets/application.css.scss
…
@import "markitup";
@import "markitup-markdown";
И наконец применяем редактор к нашему текстовому полю в форме редактирования статьи
# app/assets/javascripts/posts.js.coffee
jQuery ->
markdownSettings = {
previewParserPath: '/markdown/preview'
onShiftEnter: {keepDefault:false, openWith:'nn'}
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)
где post_content — id текстового поля. Настройки редактора (markdownSettings) взяты из документации [7].
И теперь форма редактирования выглядит примерно так
Стоит обратить внимание на одну строку
# app/assets/javascripts/posts.js.coffee
...
previewParserPath: '/markdown/preview'
Это путь к серверной странице которая сформирует превью. Реализуем ее
# 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"
И теперь у нас есть работающее превью (с указанными выше настройками вызывается последней кнопкой на панели редактора)
Полезные ссылки:
Автор: kanfet
Источник [11]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/ruby-on-rails/23530
Ссылки в тексте:
[1] haml: http://haml.info/
[2] twitter bootstrap: http://twitter.github.com/bootstrap/
[3] redcarpet: https://github.com/vmg/redcarpet
[4] документации: https://github.com/vmg/redcarpet/blob/master/README.markdown
[5] MarkItUp: http://markitup.jaysalvat.com/home/
[6] markitup-rails: https://github.com/HealthyWeb/markitup-rails
[7] документации: http://markitup.jaysalvat.com/examples/markdown/
[8] Markdown: http://ru.wikipedia.org/wiki/Markdown
[9] Исходники проекта из данной статьи: https://github.com/kanfet/markdown_example
[10] Наш новый проект: http://adminjobs.ru
[11] Источник: http://habrahabr.ru/post/163947/
Нажмите здесь для печати.