From d1b438953a261c6c466c0124bc9f56ad00aa2f8e Mon Sep 17 00:00:00 2001 From: nwb Date: Tue, 24 Jun 2014 16:26:29 +0800 Subject: [PATCH] =?UTF-8?q?wiki=5Fformat=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + .../wiki_formatting/markdown/formatter.rb | 136 ++++++++++++++++++ .../wiki_formatting/markdown/helper.rb | 45 ++++++ 3 files changed, 182 insertions(+) create mode 100644 lib/redmine/wiki_formatting/markdown/formatter.rb create mode 100644 lib/redmine/wiki_formatting/markdown/helper.rb diff --git a/.gitignore b/.gitignore index 8aa87e9f2..163982b7c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ /Gemfile.lock /db/schema.rb /Gemfile.lock +/lib/plugins/acts_as_versioned/test/debug.log diff --git a/lib/redmine/wiki_formatting/markdown/formatter.rb b/lib/redmine/wiki_formatting/markdown/formatter.rb new file mode 100644 index 000000000..c340fc1ff --- /dev/null +++ b/lib/redmine/wiki_formatting/markdown/formatter.rb @@ -0,0 +1,136 @@ +# Redmine - project management software +# Copyright (C) 2006-2014 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? + "
" +
+              Redmine::SyntaxHighlighting.highlight_by_language(code, language) +
+              "
" + else + "
" + CGI.escapeHTML(code) + "
" + 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{\[(.*?)\]}) 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..16f37c77f --- /dev/null +++ b/lib/redmine/wiki_formatting/markdown/helper.rb @@ -0,0 +1,45 @@ +# Redmine - project management software +# Copyright (C) 2006-2014 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