Nuevo plugin Redmine CKEditor 1.1.5
This commit is contained in:
parent
64924a6376
commit
698e4e7c3c
635 changed files with 24046 additions and 0 deletions
|
@ -0,0 +1,5 @@
|
|||
Description:
|
||||
Generate rich asset files for Redmine
|
||||
|
||||
Example:
|
||||
rails generate redmine_ckeditor:rich_assets
|
|
@ -0,0 +1,35 @@
|
|||
require 'rake'
|
||||
|
||||
module RedmineCkeditor
|
||||
class RichAssetsGenerator < Rails::Generators::Base
|
||||
source_root File.expand_path('../templates', __FILE__)
|
||||
desc "Generate rich asset files for Redmine"
|
||||
def create_assets
|
||||
rake "redmine_ckeditor:assets:copy"
|
||||
|
||||
gsub_file RedmineCkeditor.root.join("assets/ckeditor-contrib/plugins/richfile/plugin.js"),
|
||||
"/assets/rich/", "../images/"
|
||||
|
||||
application_js = RedmineCkeditor.root.join("assets/javascripts/application.js")
|
||||
browser_js = RedmineCkeditor.root.join("assets/javascripts/browser.js")
|
||||
|
||||
gsub_file browser_js, "opt=opt.split(',');", "opt=opt ? opt.split(',') : [];"
|
||||
|
||||
gsub_file application_js, /var CKEDITOR_BASEPATH.+$/, ""
|
||||
|
||||
gsub_file application_js, /CKEDITOR.plugins.addExternal.+$/, ""
|
||||
|
||||
gsub_file browser_js, '"/rich/files/"+', ""
|
||||
|
||||
inject_into_file browser_js,
|
||||
"\t\turl = $(item).data('relative-url-root') + url;\n",
|
||||
:after => "data('uris')[this._options.currentStyle];\n"
|
||||
|
||||
gsub_file RedmineCkeditor.root.join("assets/stylesheets/application.css"),
|
||||
'image-url("rich/', 'url("../images/'
|
||||
|
||||
append_to_file RedmineCkeditor.root.join("assets/stylesheets/editor.css"),
|
||||
"\nhtml, body {\n height: 100%;\n}\n"
|
||||
end
|
||||
end
|
||||
end
|
143
plugins/redmine_ckeditor/lib/redmine_ckeditor.rb
Normal file
143
plugins/redmine_ckeditor/lib/redmine_ckeditor.rb
Normal file
|
@ -0,0 +1,143 @@
|
|||
module RedmineCkeditor
|
||||
extend ActionView::Helpers
|
||||
|
||||
class << self
|
||||
def root
|
||||
@root ||= Pathname(File.expand_path(File.dirname(File.dirname(__FILE__))))
|
||||
end
|
||||
|
||||
def assets_root
|
||||
@assets_root ||= "#{Redmine::Utils.relative_url_root}/plugin_assets/redmine_ckeditor"
|
||||
end
|
||||
|
||||
def allowed_protocols
|
||||
@allowed_protocols ||= ckeditor_config[:allowedProtocols] || %w[
|
||||
afs aim callto ed2k feed ftp gopher http https irc mailto news
|
||||
nntp rsync rtsp sftp ssh tag telnet urn webcal xmpp
|
||||
]
|
||||
end
|
||||
|
||||
def allowed_tags
|
||||
@allowed_tags ||= ckeditor_config[:allowedTags] || %w[
|
||||
a abbr acronym address blockquote b big br caption cite code dd del dfn
|
||||
div dt em h1 h2 h3 h4 h5 h6 hr i img ins kbd li ol p pre samp small span
|
||||
strike s strong sub sup table tbody td tfoot th thead tr tt u ul var iframe
|
||||
]
|
||||
end
|
||||
|
||||
def allowed_attributes
|
||||
@allowed_attributes ||= ckeditor_config[:allowedAttributes] || %w[
|
||||
href src width height alt cite datetime title class name xml:lang abbr dir
|
||||
style align valign border cellpadding cellspacing colspan rowspan nowrap
|
||||
start reversed
|
||||
]
|
||||
end
|
||||
|
||||
def default_toolbar
|
||||
@default_toolbar ||= %w[
|
||||
Source ShowBlocks -- Undo Redo - Find Replace --
|
||||
Bold Italic Underline Strike - Subscript Superscript -
|
||||
NumberedList BulletedList - Outdent Indent Blockquote -
|
||||
JustifyLeft JustifyCenter JustifyRight JustifyBlock -
|
||||
Link Unlink - richImage Table HorizontalRule
|
||||
/
|
||||
Styles Format Font FontSize - TextColor BGColor
|
||||
].join(",")
|
||||
end
|
||||
|
||||
def config
|
||||
ActionController::Base.config
|
||||
end
|
||||
|
||||
def plugins
|
||||
@plugins ||= Dir.glob(root.join("assets/ckeditor-contrib/plugins/*")).map {
|
||||
|path| File.basename(path)
|
||||
}
|
||||
end
|
||||
|
||||
def skins
|
||||
@skins ||= Dir.glob(root.join("assets/ckeditor-contrib/skins/*")).map {
|
||||
|path| File.basename(path)
|
||||
}
|
||||
end
|
||||
|
||||
def skin_options
|
||||
options_for_select(["moono-lisa"] + skins, :selected => RedmineCkeditorSetting.skin)
|
||||
end
|
||||
|
||||
def enter_mode_options
|
||||
options_for_select({:p => 1, :br => 2, :div => 3},
|
||||
:selected => RedmineCkeditorSetting.enter_mode)
|
||||
end
|
||||
|
||||
def toolbar_location_options
|
||||
options_for_select(["top", "bottom"],
|
||||
:selected => RedmineCkeditorSetting.toolbar_location)
|
||||
end
|
||||
|
||||
def ckeditor_config
|
||||
@ckeditor_config ||= begin
|
||||
conf = {
|
||||
:extraPlugins => plugins.join(","),
|
||||
:allowedContent => true,
|
||||
:bodyClass => "wiki",
|
||||
:removePlugins => 'div,flash,forms,iframe',
|
||||
:forcePasteAsPlainText => false
|
||||
}
|
||||
file = Rails.root.join("config/ckeditor.yml")
|
||||
conf.merge!(YAML.load_file(file).symbolize_keys) if file.exist?
|
||||
conf
|
||||
end
|
||||
end
|
||||
|
||||
def options(scope_object = nil)
|
||||
scope_type = scope_object && scope_object.class.model_name.name
|
||||
scope_id = scope_object && scope_object.id
|
||||
|
||||
skin = RedmineCkeditorSetting.skin
|
||||
skin += ",#{assets_root}/ckeditor-contrib/skins/#{skin}/" if skin != "moono-lisa"
|
||||
|
||||
rich_options = Rich.options({
|
||||
:contentsCss => [stylesheet_path("application"), "#{assets_root}/stylesheets/editor.css"],
|
||||
:scoped => scope_object ? true : false,
|
||||
:allow_document_uploads => true,
|
||||
:allow_embeds => true,
|
||||
:default_style => :original,
|
||||
:richBrowserUrl => "#{Redmine::Utils.relative_url_root}/rich/files/"
|
||||
}, scope_type, scope_id)
|
||||
rich_options.delete(:removeDialogTabs)
|
||||
rich_options.delete(:format_tags)
|
||||
rich_options.delete(:stylesSet)
|
||||
rich_options.merge(ckeditor_config.merge({
|
||||
:skin => skin,
|
||||
:uiColor => RedmineCkeditorSetting.ui_color,
|
||||
:enterMode => RedmineCkeditorSetting.enter_mode,
|
||||
:shiftEnterMode => RedmineCkeditorSetting.shift_enter_mode,
|
||||
:startupOutlineBlocks => RedmineCkeditorSetting.show_blocks,
|
||||
:toolbarCanCollapse => RedmineCkeditorSetting.toolbar_can_collapse,
|
||||
:toolbarStartupExpanded => !RedmineCkeditorSetting.toolbar_can_collapse,
|
||||
:toolbarLocation => RedmineCkeditorSetting.toolbar_location,
|
||||
:toolbar => RedmineCkeditorSetting.toolbar,
|
||||
:width => RedmineCkeditorSetting.width,
|
||||
:height => RedmineCkeditorSetting.height
|
||||
}))
|
||||
end
|
||||
|
||||
def enabled?
|
||||
Setting.text_formatting == "CKEditor"
|
||||
end
|
||||
|
||||
def apply_patch
|
||||
require 'redmine_ckeditor/application_helper_patch'
|
||||
require 'redmine_ckeditor/queries_helper_patch'
|
||||
require 'redmine_ckeditor/rich_files_helper_patch'
|
||||
require 'redmine_ckeditor/journals_controller_patch'
|
||||
require 'redmine_ckeditor/messages_controller_patch'
|
||||
require 'redmine_ckeditor/mail_handler_patch'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'redmine_ckeditor/hooks/journal_listener'
|
||||
require 'redmine_ckeditor/pdf_patch'
|
||||
require 'redmine_ckeditor/tempfile_patch'
|
|
@ -0,0 +1,22 @@
|
|||
require_dependency 'application_helper'
|
||||
|
||||
module ApplicationHelper
|
||||
def ckeditor_javascripts
|
||||
root = RedmineCkeditor.assets_root
|
||||
javascript_tag("CKEDITOR_BASEPATH = '#{root}/ckeditor/';") +
|
||||
javascript_include_tag("application", :plugin => "redmine_ckeditor") +
|
||||
javascript_tag(RedmineCkeditor.plugins.map {|name|
|
||||
path = "#{root}/ckeditor-contrib/plugins/#{name}/"
|
||||
"CKEDITOR.plugins.addExternal('#{name}', '#{path}/');"
|
||||
}.join("\n"))
|
||||
end
|
||||
|
||||
def format_activity_description_with_ckeditor(text)
|
||||
if RedmineCkeditor.enabled?
|
||||
simple_format(truncate(HTMLEntities.new.decode(strip_tags(text.to_s)), :length => 120))
|
||||
else
|
||||
format_activity_description_without_ckeditor(text)
|
||||
end
|
||||
end
|
||||
alias_method_chain :format_activity_description, :ckeditor
|
||||
end
|
|
@ -0,0 +1,36 @@
|
|||
module RedmineCkeditor::Hooks
|
||||
class JournalListener < Redmine::Hook::ViewListener
|
||||
def view_journals_notes_form_after_notes(context)
|
||||
return unless RedmineCkeditor.enabled?
|
||||
|
||||
project = context[:project]
|
||||
journal = context[:journal]
|
||||
javascript_tag <<-EOT
|
||||
(function() {
|
||||
var note_id = "journal_#{journal.id}_notes";
|
||||
CKEDITOR.replace(note_id, #{RedmineCkeditor.options(project).to_json});
|
||||
var note = $("#" + note_id);
|
||||
|
||||
var save_button = note.parent().find(":submit");
|
||||
var preview_button = save_button.next();
|
||||
var cancel_button = preview_button.next().get(0);
|
||||
|
||||
save_button.click(function() {
|
||||
var editor = CKEDITOR.instances[note_id];
|
||||
note.val(editor.getData());
|
||||
editor.destroy();
|
||||
});
|
||||
|
||||
preview_button.hide();
|
||||
var cancel = cancel_button.onclick;
|
||||
cancel_button.onclick = function() {
|
||||
CKEDITOR.instances[note_id].destroy();
|
||||
cancel();
|
||||
return false;
|
||||
};
|
||||
})();
|
||||
EOT
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
require_dependency 'journals_controller'
|
||||
|
||||
module RedmineCkeditor
|
||||
module JournalsControllerPatch
|
||||
def self.included(base)
|
||||
base.send(:include, InstanceMethods)
|
||||
|
||||
base.class_eval do
|
||||
unloadable
|
||||
alias_method_chain :new, :ckeditor
|
||||
end
|
||||
end
|
||||
|
||||
module InstanceMethods
|
||||
def new_with_ckeditor
|
||||
unless RedmineCkeditor.enabled?
|
||||
new_without_ckeditor
|
||||
return
|
||||
end
|
||||
|
||||
@journal = Journal.visible.find(params[:journal_id]) if params[:journal_id]
|
||||
if @journal
|
||||
user = @journal.user
|
||||
text = @journal.notes
|
||||
else
|
||||
user = @issue.author
|
||||
text = @issue.description
|
||||
end
|
||||
@content = "<p>#{ll(I18n.locale, :text_user_wrote, user)}</p>"
|
||||
@content << "<blockquote>#{text}</blockquote><p/>"
|
||||
|
||||
render "new_with_ckeditor"
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
JournalsController.send(:include, JournalsControllerPatch)
|
||||
end
|
|
@ -0,0 +1,29 @@
|
|||
require_dependency 'mail_handler'
|
||||
|
||||
module RedmineCkeditor
|
||||
module MailHandlerPatch
|
||||
extend ActiveSupport::Concern
|
||||
include ActionView::Helpers::TextHelper
|
||||
|
||||
included do
|
||||
unloadable
|
||||
alias_method_chain :cleaned_up_text_body, :ckeditor
|
||||
alias_method_chain :extract_keyword!, :ckeditor
|
||||
end
|
||||
|
||||
def cleaned_up_text_body_with_ckeditor
|
||||
if RedmineCkeditor.enabled?
|
||||
simple_format(cleaned_up_text_body_without_ckeditor)
|
||||
else
|
||||
cleaned_up_text_body_without_ckeditor
|
||||
end
|
||||
end
|
||||
|
||||
def extract_keyword_with_ckeditor!(text, attr, format=nil)
|
||||
text = cleaned_up_text_body_without_ckeditor if RedmineCkeditor.enabled?
|
||||
extract_keyword_without_ckeditor!(text, attr, format)
|
||||
end
|
||||
end
|
||||
|
||||
MailHandler.send(:include, MailHandlerPatch)
|
||||
end
|
|
@ -0,0 +1,32 @@
|
|||
require_dependency 'messages_controller'
|
||||
|
||||
module RedmineCkeditor
|
||||
module MessagesControllerPatch
|
||||
def self.included(base)
|
||||
base.send(:include, InstanceMethods)
|
||||
|
||||
base.class_eval do
|
||||
unloadable
|
||||
alias_method_chain :quote, :ckeditor
|
||||
end
|
||||
end
|
||||
|
||||
module InstanceMethods
|
||||
def quote_with_ckeditor
|
||||
unless RedmineCkeditor.enabled?
|
||||
quote_without_ckeditor
|
||||
return
|
||||
end
|
||||
|
||||
@subject = @message.subject
|
||||
@subject = "RE: #{@subject}" unless @subject.starts_with?('RE:')
|
||||
@content = "<p>#{ll(I18n.locale, :text_user_wrote, @message.author)}</p>"
|
||||
@content << "<blockquote>#{ActionView::Base.full_sanitizer.sanitize(@message.content.to_s)}</blockquote><p/>"
|
||||
|
||||
render "quote_with_ckeditor"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
MessagesController.send(:include, MessagesControllerPatch)
|
||||
end
|
61
plugins/redmine_ckeditor/lib/redmine_ckeditor/pdf_patch.rb
Normal file
61
plugins/redmine_ckeditor/lib/redmine_ckeditor/pdf_patch.rb
Normal file
|
@ -0,0 +1,61 @@
|
|||
require_dependency 'redmine/export/pdf'
|
||||
|
||||
module RedmineCkeditor
|
||||
module PDFPatch
|
||||
def self.included(base)
|
||||
base.class_eval do
|
||||
alias_method_chain :formatted_text, :ckeditor
|
||||
alias_method_chain :get_image_filename, :ckeditor
|
||||
alias_method_chain :RDMwriteHTMLCell, :ckeditor
|
||||
end
|
||||
end
|
||||
|
||||
def formatted_text_with_ckeditor(text)
|
||||
html = formatted_text_without_ckeditor(text)
|
||||
html = HTMLEntities.new.decode(html) if RedmineCkeditor.enabled?
|
||||
html
|
||||
end
|
||||
|
||||
def RDMwriteHTMLCell_with_ckeditor(w, h, x, y, txt='', attachments=[], border=0, ln=1, fill=0)
|
||||
@tmp_images = []
|
||||
RDMwriteHTMLCell_without_ckeditor(w, h, x, y, txt, attachments, border, ln, fill)
|
||||
@tmp_images.each do |item|
|
||||
#logger.info item
|
||||
File.delete(item) if File.file?(item)
|
||||
end
|
||||
end
|
||||
|
||||
def get_image_filename_with_ckeditor(attrname)
|
||||
img = nil
|
||||
|
||||
if attrname.sub!(/^data:([^\/]+)\/([^;]+);base64,/, '')
|
||||
type = $2
|
||||
data = attrname.dup
|
||||
|
||||
# for base64 encording image such as 'clipboard_image_paste' plugin
|
||||
if @tmp_images.nil?
|
||||
@tmp_images = []
|
||||
end
|
||||
|
||||
tmp = Tempfile.new([@tmp_images.length.to_s, '.'+type])
|
||||
img = tmp.path
|
||||
tmp.close
|
||||
|
||||
@tmp_images << img
|
||||
File.open(img, 'wb') do |f|
|
||||
f.write(Base64.decode64(data))
|
||||
end
|
||||
else
|
||||
# for CKEditor file uploader with 'rich' plugin
|
||||
img = if attrname.include?("/rich/rich_files/rich_files/")
|
||||
Rails.root.join("public#{URI.decode(attrname)}").to_s
|
||||
else
|
||||
get_image_filename_without_ckeditor(attrname)
|
||||
end
|
||||
end
|
||||
img
|
||||
end
|
||||
end
|
||||
|
||||
Redmine::Export::PDF::ITCPDF.send(:include, PDFPatch)
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
require_dependency 'queries_helper'
|
||||
|
||||
module QueriesHelper
|
||||
def csv_value_with_ckeditor(column, issue, value)
|
||||
if RedmineCkeditor.enabled? && column.name == :description
|
||||
text = Rails::Html::FullSanitizer.new.sanitize(value.to_s)
|
||||
text.gsub(/(?:\r\n\t*)+/, "\r").gsub(" ", " ").strip
|
||||
else
|
||||
csv_value_without_ckeditor(column, issue, value)
|
||||
end
|
||||
end
|
||||
alias_method_chain :csv_value, :ckeditor
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
require_dependency 'rich/files_helper'
|
||||
|
||||
module RedmineCkeditor
|
||||
module RichFilesHelperPatch
|
||||
def self.included(base)
|
||||
base.send(:include, InstanceMethods)
|
||||
base.class_eval do
|
||||
alias_method_chain :thumb_for_file, :redmine
|
||||
end
|
||||
end
|
||||
|
||||
module InstanceMethods
|
||||
def thumb_for_file_with_redmine(file)
|
||||
Redmine::Utils.relative_url_root + if file.simplified_type == "image"
|
||||
file.rich_file.url(:rich_thumb)
|
||||
else
|
||||
"/plugin_assets/redmine_ckeditor/images/document-thumb.png"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Rich::FilesHelper.send(:include, RichFilesHelperPatch)
|
||||
end
|
9
plugins/redmine_ckeditor/lib/redmine_ckeditor/tempfile_patch.rb
Executable file
9
plugins/redmine_ckeditor/lib/redmine_ckeditor/tempfile_patch.rb
Executable file
|
@ -0,0 +1,9 @@
|
|||
class Tempfile
|
||||
def initialize_with_binmode(basename, *rest)
|
||||
initialize_without_binmode(basename, *rest).tap do |f|
|
||||
f.binmode if basename == "raw-upload."
|
||||
end
|
||||
end
|
||||
|
||||
alias_method_chain :initialize, :binmode
|
||||
end
|
|
@ -0,0 +1,38 @@
|
|||
module RedmineCkeditor::WikiFormatting
|
||||
class Formatter
|
||||
include Redmine::WikiFormatting::LinksHelper
|
||||
|
||||
def initialize(text)
|
||||
@text = text
|
||||
end
|
||||
|
||||
def to_html(&block)
|
||||
preserved = []
|
||||
text = @text.gsub(/<pre>\s*(.*?)\s*<\/pre>/m) {|m|
|
||||
content = if matched = $1.match(/<code\s+class="(\w+)">[\r\n]*(.*?)[\r\n]*<\/code>/m)
|
||||
lang, code = matched.captures
|
||||
code = Redmine::SyntaxHighlighting.highlight_by_language(code, lang)
|
||||
%Q[<pre>\n<code class="#{lang} syntaxhl">#{code}</code>\n</pre>]
|
||||
else
|
||||
m
|
||||
end
|
||||
preserved.push(content)
|
||||
"____preserved_#{preserved.size}____"
|
||||
}.gsub(/{{.*?}}/m) {|m|
|
||||
preserved.push(m)
|
||||
"____preserved_#{preserved.size}____"
|
||||
}
|
||||
|
||||
auto_link!(text)
|
||||
text = ActionView::Base.white_list_sanitizer.sanitize(text,
|
||||
:tags => RedmineCkeditor.allowed_tags,
|
||||
:attributes => RedmineCkeditor.allowed_attributes
|
||||
)
|
||||
|
||||
preserved.each.with_index(1) {|content, i|
|
||||
text.gsub!("____preserved_#{i}____", content)
|
||||
}
|
||||
text
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,60 @@
|
|||
module RedmineCkeditor::WikiFormatting
|
||||
module Helper
|
||||
def replace_editor_tag(field_id)
|
||||
javascript_tag <<-EOT
|
||||
$(document).ready(function() {
|
||||
#{replace_editor_script(field_id)}
|
||||
});
|
||||
EOT
|
||||
end
|
||||
|
||||
def replace_editor_script(field_id)
|
||||
<<-EOT
|
||||
(function() {
|
||||
var id = '#{field_id}';
|
||||
var textarea = document.getElementById(id);
|
||||
if (!textarea) return;
|
||||
|
||||
var editor = CKEDITOR.replace(textarea, #{RedmineCkeditor.options(@project).to_json});
|
||||
editor.on("change", function() { textarea.value = editor.getSnapshot(); });
|
||||
})();
|
||||
EOT
|
||||
end
|
||||
|
||||
def overwrite_functions
|
||||
javascript_tag <<-EOT
|
||||
function showAndScrollTo(id, focus) {
|
||||
var elem = $("#" + id);
|
||||
elem.show();
|
||||
if (focus != null && CKEDITOR.instances.hasOwnProperty(focus)) { CKEDITOR.instances[focus].focus(); }
|
||||
$('html, body').animate({scrollTop: elem.offset().top}, 100);
|
||||
}
|
||||
|
||||
function destroyEditor(id) {
|
||||
if (CKEDITOR.instances[id]) CKEDITOR.instances[id].destroy();
|
||||
}
|
||||
EOT
|
||||
end
|
||||
|
||||
def initial_setup
|
||||
overwrite_functions
|
||||
end
|
||||
|
||||
def wikitoolbar_for(field_id)
|
||||
if params[:format] == "js"
|
||||
javascript_tag(replace_editor_script(field_id))
|
||||
else
|
||||
ckeditor_javascripts +
|
||||
stylesheet_link_tag('editor', :plugin => 'redmine_ckeditor') +
|
||||
initial_setup + replace_editor_tag(field_id)
|
||||
end
|
||||
end
|
||||
|
||||
def initial_page_content(page)
|
||||
"<h1>#{ERB::Util.html_escape page.pretty_title}</h1>"
|
||||
end
|
||||
|
||||
def heads_for_wiki_formatter
|
||||
end
|
||||
end
|
||||
end
|
100
plugins/redmine_ckeditor/lib/tasks/ckeditor.rake
Normal file
100
plugins/redmine_ckeditor/lib/tasks/ckeditor.rake
Normal file
|
@ -0,0 +1,100 @@
|
|||
namespace :redmine_ckeditor do
|
||||
namespace :assets do
|
||||
desc "copy assets"
|
||||
task :copy => :environment do
|
||||
env = Sprockets::Environment.new(RedmineCkeditor.root)
|
||||
Rails.application.config.assets.paths.each do |path|
|
||||
env.append_path(path)
|
||||
end
|
||||
env.append_path("app/assets/javascripts")
|
||||
%w(application.js browser.js).each do |asset|
|
||||
assets = env.find_asset(asset)
|
||||
assets.write_to(RedmineCkeditor.root.join("assets/javascripts", asset))
|
||||
end
|
||||
|
||||
ckeditor = RedmineCkeditor.root.join("assets/ckeditor")
|
||||
rm_rf ckeditor
|
||||
cp_r RedmineCkeditor.root.join("app/assets/javascripts/ckeditor-releases"), ckeditor
|
||||
rm ckeditor.join(".git")
|
||||
end
|
||||
end
|
||||
|
||||
class Migration
|
||||
FORMATS = %w[textile markdown html]
|
||||
|
||||
def initialize(projects, from, to)
|
||||
@from = from
|
||||
@to = to
|
||||
@projects = projects
|
||||
end
|
||||
|
||||
def start
|
||||
[@from, @to].each do |format|
|
||||
next if FORMATS.include?(format)
|
||||
puts "#{format} format is not supported."
|
||||
puts "Available formats: #{FORMATS.join(", ")}"
|
||||
return
|
||||
end
|
||||
|
||||
messages = [
|
||||
"*** WARNING ***",
|
||||
"It is strongly recommended to backup your database before migration, because it cannot be rolled back completely.",
|
||||
"***************"
|
||||
]
|
||||
|
||||
if @projects.empty?
|
||||
@projects = Project.all
|
||||
messages << "projects: ALL"
|
||||
else
|
||||
messages << "projects: #{@projects.pluck(:identifier).join(",")}"
|
||||
end
|
||||
messages << "migration: #{@from} to #{@to}"
|
||||
|
||||
messages.each {|message| puts message}
|
||||
print "Do you want to continue? (type 'y' to continue): "
|
||||
unless STDIN.gets.chomp == 'y'
|
||||
puts "Cancelled"
|
||||
return
|
||||
end
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
@projects.each do |project|
|
||||
puts "project #{project.name}"
|
||||
project.update_column(:description, convert(project.description))
|
||||
migrate(:issues, project.issues, :description)
|
||||
migrate(:journals, Journal.where(:journalized_type => "Issue",
|
||||
:journalized_id => project.issues), :notes)
|
||||
migrate(:documents, project.documents, :description)
|
||||
migrate(:messages, Message.where(:board_id => project.boards), :content)
|
||||
migrate(:news, project.news, :description)
|
||||
migrate(:comments, Comment.where(:commented_type => "News",
|
||||
:commented_id => project.news), :comments)
|
||||
migrate(:wiki, WikiContent.where(:page_id => project.wiki.pages), :text) if project.wiki
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def migrate(type, records, column)
|
||||
n = records.count
|
||||
return if n == 0
|
||||
records.each_with_index do |record, i|
|
||||
print "\rMigrating #{type} ... (#{i}/#{n})"
|
||||
record.update_column(column, convert(record.send(column)))
|
||||
end
|
||||
puts "\rMigrating #{type} ... done "
|
||||
end
|
||||
|
||||
def convert(text)
|
||||
text && PandocRuby.convert(text, from: @from, to: @to)
|
||||
end
|
||||
end
|
||||
|
||||
desc "Migrate text to html"
|
||||
task :migrate => :environment do
|
||||
projects = Project.where(:identifier => ENV['PROJECT'].to_s.split(","))
|
||||
from = ENV['FROM'] || Setting.text_formatting
|
||||
from = "html" if from == "CKEditor"
|
||||
to = ENV['TO'] || "html"
|
||||
Migration.new(projects, from, to).start
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue