diff options
author | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2013-12-23 13:05:10 +0000 |
---|---|---|
committer | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2013-12-23 13:05:10 +0000 |
commit | 471e01ca5059f892888f78e2278dd41d742a4b75 (patch) | |
tree | a07ecd3d8911cf0e6ce1220584fa2c10ed81b9ab /lib/redmine/wiki_formatting | |
parent | 6311ade82708b63b83d30278a1af4c05af4aee6e (diff) | |
download | redmine-471e01ca5059f892888f78e2278dd41d742a4b75.tar.gz redmine-471e01ca5059f892888f78e2278dd41d742a4b75.zip |
Adds experimental support for Markdown formatting with redcarpet (#15520).
git-svn-id: http://svn.redmine.org/redmine/trunk@12452 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'lib/redmine/wiki_formatting')
-rw-r--r-- | lib/redmine/wiki_formatting/markdown/formatter.rb | 136 | ||||
-rw-r--r-- | lib/redmine/wiki_formatting/markdown/helper.rb | 45 |
2 files changed, 181 insertions, 0 deletions
diff --git a/lib/redmine/wiki_formatting/markdown/formatter.rb b/lib/redmine/wiki_formatting/markdown/formatter.rb new file mode 100644 index 000000000..19ee46693 --- /dev/null +++ b/lib/redmine/wiki_formatting/markdown/formatter.rb @@ -0,0 +1,136 @@ +# Redmine - project management software +# Copyright (C) 2006-2013 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'cgi' + +module Redmine + module WikiFormatting + module Markdown + class HTML < Redcarpet::Render::HTML + include ActionView::Helpers::TagHelper + + def link(link, title, content) + css = nil + unless link && link.starts_with?('/') + css = 'external' + end + content_tag('a', content.html_safe, :href => link, :title => title, :class => css) + end + + def block_code(code, language) + if language.present? + "<pre><code class=\"#{CGI.escapeHTML language} syntaxhl\">" + + Redmine::SyntaxHighlighting.highlight_by_language(code, language) + + "</code></pre>" + else + "<pre>" + CGI.escapeHTML(code) + "</pre>" + end + end + end + + class Formatter + def initialize(text) + @text = text + end + + def to_html(*args) + html = formatter.render(@text) + # restore wiki links eg. [[Foo]] + html.gsub!(%r{\[<a href="(.*?)">(.*?)</a>\]}) do + "[[#{$2}]]" + end + # restore Redmine links with double-quotes, eg. version:"1.0" + html.gsub!(/(\w):"(.+?)"/) do + "#{$1}:\"#{$2}\"" + end + html + end + + def get_section(index) + section = extract_sections(index)[1] + hash = Digest::MD5.hexdigest(section) + return section, hash + end + + def update_section(index, update, hash=nil) + t = extract_sections(index) + if hash.present? && hash != Digest::MD5.hexdigest(t[1]) + raise Redmine::WikiFormatting::StaleSectionError + end + t[1] = update unless t[1].blank? + t.reject(&:blank?).join "\n\n" + end + + def extract_sections(index) + sections = ['', '', ''] + offset = 0 + i = 0 + l = 1 + inside_pre = false + @text.split(/(^(?:.+\r?\n\r?(?:\=+|\-+)|#+.+|~~~.*)\s*$)/).each do |part| + level = nil + if part =~ /\A~{3,}(\S+)?\s*$/ + if $1 + if !inside_pre + inside_pre = true + end + else + inside_pre = !inside_pre + end + elsif inside_pre + # nop + elsif part =~ /\A(#+).+/ + level = $1.size + elsif part =~ /\A.+\r?\n\r?(\=+|\-+)\s*$/ + level = $1.include?('=') ? 1 : 2 + end + if level + i += 1 + if offset == 0 && i == index + # entering the requested section + offset = 1 + l = level + elsif offset == 1 && i > index && level <= l + # leaving the requested section + offset = 2 + end + end + sections[offset] << part + end + sections.map(&:strip) + end + + private + + def formatter + @@formatter ||= Redcarpet::Markdown.new( + Redmine::WikiFormatting::Markdown::HTML.new( + :filter_html => true, + :hard_wrap => true + ), + :autolink => true, + :fenced_code_blocks => true, + :space_after_headers => true, + :tables => true, + :strikethrough => true, + :superscript => true + ) + end + end + end + end +end diff --git a/lib/redmine/wiki_formatting/markdown/helper.rb b/lib/redmine/wiki_formatting/markdown/helper.rb new file mode 100644 index 000000000..2619cb71e --- /dev/null +++ b/lib/redmine/wiki_formatting/markdown/helper.rb @@ -0,0 +1,45 @@ +# Redmine - project management software +# Copyright (C) 2006-2013 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +module Redmine + module WikiFormatting + module Markdown + module Helper + def wikitoolbar_for(field_id) + heads_for_wiki_formatter + javascript_tag("var wikiToolbar = new jsToolBar(document.getElementById('#{field_id}')); wikiToolbar.draw();") + end + + def initial_page_content(page) + "# #{@page.pretty_title}" + end + + def heads_for_wiki_formatter + unless @heads_for_wiki_formatter_included + content_for :header_tags do + javascript_include_tag('jstoolbar/jstoolbar') + + javascript_include_tag('jstoolbar/markdown') + + javascript_include_tag("jstoolbar/lang/jstoolbar-#{current_language.to_s.downcase}") + + stylesheet_link_tag('jstoolbar') + end + @heads_for_wiki_formatter_included = true + end + end + end + end + end +end |