В одном новом проекте, написанном на ruby on rails, была поставлена задача дать возможность пользователю использовать markdown-разметку для форматирования текста. Один из вариантов реализации описан в данной статье.
Статья не описывает основы ruby on rails. Я подразумеваю, что читатель может создать проект и запустить его в своей любимой IDE / из консоли / еще как. Плюс в конце статьи есть ссылка на исходники демонстрационного проекта.
Одно уточнение: я использую haml для view-шек и twitter bootstrap для оформления.
Допустим что у нас есть приложение. И нам надо добавить в него класс «Статья» с полями заголовок и содержимое. Поле содержимое будет типа text. К нему то нам и необходимо применить markdown-разметку.
Добавим наш класс и заодно контроллер и view-шки
rails generate scaffold Post title content:text rake db:migrate
Markdown парсер
В качестве парсера используем redcarpet
# 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 разметки. При желании можно написать свой рендерер или унаследовать от существующих. Возможные значения опций для рендерера и парсера можно посмотреть в документации.
Применяем 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) ![image](http://placehold.it/350x150) ``` class Cat < Animal def say "Meow!" end end ```
то увидим примерно следующую картину
Markdown редактор
Добавим в проект визуальный редактор MarkItUp. Для этого можно использовать гем markitup-rails
# 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:'\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)
где post_content — id текстового поля. Настройки редактора (markdownSettings) взяты из документации.
И теперь форма редактирования выглядит примерно так
Предварительный просмотр
Стоит обратить внимание на одну строку
# 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"
И теперь у нас есть работающее превью (с указанными выше настройками вызывается последней кнопкой на панели редактора)
Полезные ссылки:
- Markdown
- Redcarpet
- MarkItUp
- Исходники проекта из данной статьи
- Наш новый проект, где можно посмотреть реальное применение описанного в статье алгоритма
ссылка на оригинал статьи http://habrahabr.ru/company/centosadmin/blog/163947/
Добавить комментарий