Actualizar plugin CKEditor a 1.2.3

This commit is contained in:
Manuel Cillero 2020-11-30 11:19:32 +01:00
parent fd78375294
commit dda045bde9
23 changed files with 513 additions and 240 deletions

3
plugins/redmine_ckeditor/.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "app/assets/javascripts/ckeditor-releases"]
path = app/assets/javascripts/ckeditor-releases
url = git://github.com/ckeditor/ckeditor-releases.git

View file

@ -1,7 +1,9 @@
gem 'rich', git: 'https://github.com/a-ono/rich.git'
source 'https://rubygems.org'
gem 'rich', git: 'https://github.com/a-ono/rich.git', tag: '1.5.2'
gem 'kaminari'
gem 'htmlentities'
gem 'paperclip', '~> 4.2.1'
gem 'paperclip', '~> 6.1.0'
gem 'pandoc-ruby'
# It is needed for upgrading CKEditor

View file

@ -17,7 +17,9 @@ See {the official site}[http://ckeditor.com/] for more details.
# Mac OS X
brew install imagemagick
* Redmine 3.0.x, (version {1.1.5}[https://github.com/a-ono/redmine_ckeditor/releases/tag/1.1.5])
* Redmine 4.x (version {1.2.3}[https://github.com/a-ono/redmine_ckeditor/releases/tag/1.2.3])
* Redmine 3.x, (version {1.1.7}[https://github.com/a-ono/redmine_ckeditor/releases/tag/1.1.7])
* Redmine 2.3.x, Ruby 1.9.2 or higher (version {1.0.20}[https://github.com/a-ono/redmine_ckeditor/releases/tag/1.0.20])
@ -33,7 +35,7 @@ See {the official site}[http://ckeditor.com/] for more details.
== Plugin installation and setup
1. Copy the plugin directory into the plugins directory (make sure the name is redmine_ckeditor)
1. Download the {zip package}[https://github.com/a-ono/redmine_ckeditor/archive/master.zip] and extract the directory that it contains into the plugins directory (make sure the name is redmine_ckeditor)
2. Install the required gems (in the Redmine root directory)
bundle install --without development test
3. Execute migration
@ -84,7 +86,9 @@ This plugin stores contents in HTML format and renders as is.
If you have old contents, these look weird.
You can use {redmine_per_project_formatting}[https://github.com/a-ono/redmine_per_project_formatting] plugin for backward compatibility or execute redmine_ckeditor:migrate task for migrating old text to HTML.
rake redmine_ckeditor:migrate RAILS_ENV=production [PROJECT=project_identifier1,project_identifier2] [FROM=textile] [TO=html]
rake redmine_ckeditor:migrate RAILS_ENV=production FROM=textile TO=html
You can also use PROJECT parameter to migrate only specific projets
rake redmine_ckeditor:migrate RAILS_ENV=production PROJECT=project_identifier1,project_identifier2 FROM=textile TO=html
This task requires to {install Pandoc}[http://johnmacfarlane.net/pandoc/installing.html].
== Upgrading CKEditor (for development)

View file

@ -0,0 +1,316 @@
/**
* @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or http://ckeditor.com/license
*/
/*
skin.js
=========
In this file we interact with the CKEditor JavaScript API to register the skin
and enable additional skin related features.
The level of complexity of this file depends on the features available in the
skin. There is only one mandatory line of code to be included here, which is
setting CKEDITOR.skin.name. All the rest is optional, but recommended to be
implemented as they make higher quality skins.
For this skin, the following tasks are achieved in this file:
1. Register the skin.
2. Register browser specific skin files.
3. Define the "Chameleon" feature.
4. Register the skin icons, to have them used on the development version of
the skin.
*/
// 1. Register the skin
// ----------------------
// The CKEDITOR.skin.name property must be set to the skin name. This is a
// lower-cased name, which must match the skin folder name as well as the value
// used on config.skin to tell the editor to use the skin.
//
// This is the only mandatory property to be defined in this file.
CKEDITOR.skin.name = 'moono';
// 2. Register browser specific skin files
// -----------------------------------------
// (http://docs.cksource.com/CKEditor_4.x/Skin_SDK/Browser_Hacks)
//
// To help implementing browser specific "hacks" to the skin files and have it
// easy to maintain, it is possible to have dedicated files for such browsers,
// for both the main skin CSS files: editor.css and dialog.css.
//
// The browser files must be named after the main file names, appended by an
// underscore and the browser name (e.g. editor_ie.css, dialog_ie8.css).
//
// The accepted browser names must match the CKEDITOR.env properties. The most
// common names are: ie, webkit and gecko. Check the documentation for the complete
// list:
// http://docs.ckeditor.com/#!/api/CKEDITOR.env
//
// Internet explorer is an expection and the browser version is also accepted
// (ie7, ie8, ie9, ie10), as well as a special name for IE in Quirks mode (iequirks).
//
// The available browser specific files must be set separately for editor.css
// and dialog.css.
CKEDITOR.skin.ua_editor = 'ie,iequirks,ie7,ie8,gecko';
CKEDITOR.skin.ua_dialog = 'ie,iequirks,ie7,ie8';
// 3. Define the "Chameleon" feature
// -----------------------------------
// (http://docs.cksource.com/CKEditor_4.x/Skin_SDK/Chameleon)
//
// "Chameleon" is a unique feature available in CKEditor. It makes it possible
// to end users to specify which color to use as the basis for the editor UI.
// It is enough to set config.uiColor to any color value and voila, the UI is
// colored.
//
// The only detail here is that the skin itself must be compatible with the
// Chameleon feature. That's because the skin CSS files are the responsible to
// apply colors in the UI and each skin do that in different way and on
// different places.
//
// Implementing the Chameleon feature requires a bit of JavaScript programming.
// The CKEDITOR.skin.chameleon function must be defined. It must return the CSS
// "template" to be used to change the color of a specific CKEditor instance
// available in the page. When a color change is required, this template is
// appended to the page holding the editor, overriding styles defined in the
// skin files.
//
// The "$color" placeholder can be used in the returned string. It'll be
// replaced with the desired color.
CKEDITOR.skin.chameleon = ( function() {
// This method can be used to adjust colour brightness of various element.
// Colours are accepted in 7-byte hex format, for example: #00ff00.
// Brightness ratio must be a float number within [-1, 1],
// where -1 is black, 1 is white and 0 is the original colour.
var colorBrightness = ( function() {
function channelBrightness( channel, ratio ) {
var brighten = ratio < 0 ? (
0 | channel * ( 1 + ratio )
) : (
0 | channel + ( 255 - channel ) * ratio
);
return ( '0' + brighten.toString( 16 ) ).slice( -2 );
}
return function( hexColor, ratio ) {
var channels = hexColor.match( /[^#]./g );
for ( var i = 0 ; i < 3 ; i++ )
channels[ i ] = channelBrightness( parseInt( channels[ i ], 16 ), ratio );
return '#' + channels.join( '' );
};
} )(),
// Use this function just to avoid having to repeat all these rules on
// several places of our template.
verticalGradient = ( function() {
var template = new CKEDITOR.template( 'background:#{to};' +
'background-image:linear-gradient(to bottom,{from},{to});' +
'filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr=\'{from}\',endColorstr=\'{to}\');' );
return function( from, to ) {
return template.output( { from: from, to: to } );
};
} )(),
// Style templates for various user interface parts:
// * Default editor template.
// * Default panel template.
templates = {
editor: new CKEDITOR.template(
'{id}.cke_chrome [border-color:{defaultBorder};] ' +
'{id} .cke_top [ ' +
'{defaultGradient}' +
'border-bottom-color:{defaultBorder};' +
'] ' +
'{id} .cke_bottom [' +
'{defaultGradient}' +
'border-top-color:{defaultBorder};' +
'] ' +
'{id} .cke_resizer [border-right-color:{ckeResizer}] ' +
// Dialogs.
'{id} .cke_dialog_title [' +
'{defaultGradient}' +
'border-bottom-color:{defaultBorder};' +
'] ' +
'{id} .cke_dialog_footer [' +
'{defaultGradient}' +
'outline-color:{defaultBorder};' +
'border-top-color:{defaultBorder};' + // IE7 doesn't use outline.
'] ' +
'{id} .cke_dialog_tab [' +
'{lightGradient}' +
'border-color:{defaultBorder};' +
'] ' +
'{id} .cke_dialog_tab:hover [' +
'{mediumGradient}' +
'] ' +
'{id} .cke_dialog_contents [' +
'border-top-color:{defaultBorder};' +
'] ' +
'{id} .cke_dialog_tab_selected, {id} .cke_dialog_tab_selected:hover [' +
'background:{dialogTabSelected};' +
'border-bottom-color:{dialogTabSelectedBorder};' +
'] ' +
'{id} .cke_dialog_body [' +
'background:{dialogBody};' +
'border-color:{defaultBorder};' +
'] ' +
// Toolbars, buttons.
'{id} .cke_toolgroup [' +
'{lightGradient}' +
'border-color:{defaultBorder};' +
'] ' +
'{id} a.cke_button_off:hover, {id} a.cke_button_off:focus, {id} a.cke_button_off:active [' +
'{mediumGradient}' +
'] ' +
'{id} .cke_button_on [' +
'{ckeButtonOn}' +
'] ' +
'{id} .cke_toolbar_separator [' +
'background-color: {ckeToolbarSeparator};' +
'] ' +
// Combo buttons.
'{id} .cke_combo_button [' +
'border-color:{defaultBorder};' +
'{lightGradient}' +
'] ' +
'{id} a.cke_combo_button:hover, {id} a.cke_combo_button:focus, {id} .cke_combo_on a.cke_combo_button [' +
'border-color:{defaultBorder};' +
'{mediumGradient}' +
'] ' +
// Elementspath.
'{id} .cke_path_item [' +
'color:{elementsPathColor};' +
'] ' +
'{id} a.cke_path_item:hover, {id} a.cke_path_item:focus, {id} a.cke_path_item:active [' +
'background-color:{elementsPathBg};' +
'] ' +
'{id}.cke_panel [' +
'border-color:{defaultBorder};' +
'] '
),
panel: new CKEDITOR.template(
// Panel drop-downs.
'.cke_panel_grouptitle [' +
'{lightGradient}' +
'border-color:{defaultBorder};' +
'] ' +
// Context menus.
'.cke_menubutton_icon [' +
'background-color:{menubuttonIcon};' +
'] ' +
'.cke_menubutton:hover .cke_menubutton_icon, .cke_menubutton:focus .cke_menubutton_icon, .cke_menubutton:active .cke_menubutton_icon [' +
'background-color:{menubuttonIconHover};' +
'] ' +
'.cke_menuseparator [' +
'background-color:{menubuttonIcon};' +
'] ' +
// Color boxes.
'a:hover.cke_colorbox, a:focus.cke_colorbox, a:active.cke_colorbox [' +
'border-color:{defaultBorder};' +
'] ' +
'a:hover.cke_colorauto, a:hover.cke_colormore, a:focus.cke_colorauto, a:focus.cke_colormore, a:active.cke_colorauto, a:active.cke_colormore [' +
'background-color:{ckeColorauto};' +
'border-color:{defaultBorder};' +
'] '
)
};
return function( editor, part ) {
var uiColor = editor.uiColor,
// The following are CSS styles used in templates.
// Styles are generated according to current editor.uiColor.
templateStyles = {
// CKEditor instances have a unique ID, which is used as class name into
// the outer container of the editor UI (e.g. ".cke_1").
//
// The Chameleon feature is available for each CKEditor instance,
// independently. Because of this, we need to prefix all CSS selectors with
// the unique class name of the instance.
id: '.' + editor.id,
// These styles are used by various UI elements.
defaultBorder: colorBrightness( uiColor, -0.1 ),
defaultGradient: verticalGradient( colorBrightness( uiColor, 0.9 ), uiColor ),
lightGradient: verticalGradient( colorBrightness( uiColor, 1 ), colorBrightness( uiColor, 0.7 ) ),
mediumGradient: verticalGradient( colorBrightness( uiColor, 0.8 ), colorBrightness( uiColor, 0.5 ) ),
// These are for specific UI elements.
ckeButtonOn: verticalGradient( colorBrightness( uiColor, 0.6 ), colorBrightness( uiColor, 0.7 ) ),
ckeResizer: colorBrightness( uiColor, -0.4 ),
ckeToolbarSeparator: colorBrightness( uiColor, 0.5 ),
ckeColorauto: colorBrightness( uiColor, 0.8 ),
dialogBody: colorBrightness( uiColor, 0.7 ),
// Use gradient instead of simple hex to avoid further filter resetting in IE.
dialogTabSelected: verticalGradient( '#FFFFFF', '#FFFFFF' ),
dialogTabSelectedBorder: '#FFF',
elementsPathColor: colorBrightness( uiColor, -0.6 ),
elementsPathBg: uiColor,
menubuttonIcon: colorBrightness( uiColor, 0.5 ),
menubuttonIconHover: colorBrightness( uiColor, 0.3 )
};
return templates[ part ]
.output( templateStyles )
.replace( /\[/g, '{' ) // Replace brackets with braces.
.replace( /\]/g, '}' );
};
} )();
// %REMOVE_START%
// 4. Register the skin icons for development purposes only
// ----------------------------------------------------------
// (http://docs.cksource.com/CKEditor_4.x/Skin_SDK/Icons)
//
// This code is here just to make the skin work fully when using its "source"
// version. Without this, the skin will still work, but its icons will not be
// used (again, on source version only).
//
// This block of code is not necessary on the release version of the skin.
// Because of this it is very important to include it inside the REMOVE_START
// and REMOVE_END comment markers, so the skin builder will properly clean
// things up.
//
// If a required icon is not available here, the plugin defined icon will be
// used instead. This means that a skin is not required to provide all icons.
// Actually, it is not required to provide icons at all.
( function() {
// The available icons. This list must match the file names (without
// extension) available inside the "icons" folder.
var icons = ( 'about,anchor-rtl,anchor,bgcolor,bidiltr,bidirtl,blockquote,' +
'bold,bulletedlist-rtl,bulletedlist,button,checkbox,copy-rtl,copy,copyformatting,' +
'creatediv,cut-rtl,cut,docprops-rtl,docprops,find-rtl,find,flash,form,' +
'hiddenfield,horizontalrule,icons,iframe,image,imagebutton,indent-rtl,' +
'indent,italic,justifyblock,justifycenter,justifyleft,justifyright,' +
'link,maximize,newpage-rtl,newpage,numberedlist-rtl,numberedlist,' +
'outdent-rtl,outdent,pagebreak-rtl,pagebreak,paste-rtl,paste,' +
'pastefromword-rtl,pastefromword,pastetext-rtl,pastetext,preview-rtl,' +
'preview,print,radio,redo-rtl,redo,removeformat,replace,save,scayt,' +
'select-rtl,select,selectall,showblocks-rtl,showblocks,smiley,' +
'source-rtl,source,specialchar,spellchecker,strike,subscript,' +
'superscript,table,templates-rtl,templates,textarea-rtl,textarea,' +
'textcolor,textfield-rtl,textfield,uicolor,underline,undo-rtl,undo,unlink' ).split( ',' );
var iconsFolder = CKEDITOR.getUrl( CKEDITOR.skin.path() + 'icons/' + ( CKEDITOR.env.hidpi ? 'hidpi/' : '' ) );
for ( var i = 0; i < icons.length; i++ ) {
CKEDITOR.skin.addIcon( icons[ i ], iconsFolder + icons[ i ] + '.png' );
}
} )();
// %REMOVE_END%

View file

@ -0,0 +1,15 @@
pt:
ckeditor_skin: Skin
ckeditor_ui_color: Cor UI
ckeditor_enter_mode: Modo do ENTER
ckeditor_startup_show_blocks: Blocos de exibição de inicialização
ckeditor_toolbar_can_collapse: Barra de ferramentas pode minimizar
ckeditor_toolbar_location: Barra de ferramentas localização
ckeditor_toolbar_buttons: Barra de ferramentas botões
ckeditor_width: Largura
ckeditor_height: Altura
add: Adicionar
remove: Remover
separator: Separador
subgroup: Subgrupo
line_break: Quebra de linha

View file

@ -1,5 +1,5 @@
# This migration comes from rich (originally 20111002142937)
class CreateRichRichImages < ActiveRecord::Migration
class CreateRichRichImages < ActiveRecord::Migration[4.2]
def change
create_table :rich_rich_images do |t|

View file

@ -1,5 +1,5 @@
# This migration comes from rich (originally 20111117202133)
class AddUriCacheToRichImage < ActiveRecord::Migration
class AddUriCacheToRichImage < ActiveRecord::Migration[4.2]
def change
add_column :rich_rich_images, :uri_cache, :text
end

View file

@ -1,5 +1,5 @@
# This migration comes from rich (originally 20111201095829)
class RefactorImageToFile < ActiveRecord::Migration
class RefactorImageToFile < ActiveRecord::Migration[4.2]
def change
rename_table :rich_rich_images, :rich_rich_files

View file

@ -1,7 +1,7 @@
require 'redmine'
require 'redmine_ckeditor'
Rails.application.config.to_prepare do
ActiveSupport::Reloader.to_prepare do
RedmineCkeditor.apply_patch
end
@ -9,8 +9,8 @@ Redmine::Plugin.register :redmine_ckeditor do
name 'Redmine CKEditor plugin'
author 'Akihiro Ono'
description 'This is a CKEditor plugin for Redmine'
version '1.1.5'
requires_redmine :version_or_higher => '3.0.0'
version '1.2.3'
requires_redmine :version_or_higher => '4.0.0'
url 'http://github.com/a-ono/redmine_ckeditor'
settings(:partial => 'settings/ckeditor')
@ -19,4 +19,4 @@ Redmine::Plugin.register :redmine_ckeditor do
RedmineCkeditor::WikiFormatting::Helper
end
Loofah::HTML5::WhiteList::ALLOWED_PROTOCOLS.replace RedmineCkeditor.allowed_protocols
(Loofah::VERSION >= "2.3.0" ? Loofah::HTML5::SafeList : Loofah::HTML5::WhiteList)::ALLOWED_PROTOCOLS.replace RedmineCkeditor.allowed_protocols

View file

@ -1,4 +1,5 @@
require 'rake'
require 'rails/generators'
module RedmineCkeditor
class RichAssetsGenerator < Rails::Generators::Base

View file

@ -128,17 +128,22 @@ module RedmineCkeditor
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'
::ApplicationController.send :helper, ApplicationHelperPatch
::JournalsController.prepend JournalsControllerPatch
::MailHandler.prepend MailHandlerPatch
::MessagesController.prepend MessagesControllerPatch
::QueriesController.send :helper, QueriesHelperPatch
::Rich::FilesController.send :helper, RichFilesHelperPatch
end
end
end
require 'redmine_ckeditor/hooks/views_layouts_hook'
require 'redmine_ckeditor/hooks/journal_listener'
require 'redmine_ckeditor/helper'
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'
require 'redmine_ckeditor/pdf_patch'
require 'redmine_ckeditor/tempfile_patch'

View file

@ -1,22 +1,13 @@
require_dependency 'application_helper'
module RedmineCkeditor
module ApplicationHelperPatch
include RedmineCkeditor::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)
def format_activity_description(text)
if RedmineCkeditor.enabled?
simple_format(truncate(HTMLEntities.new.decode(strip_tags(text.to_s)), :length => 120))
else
format_activity_description_without_ckeditor(text)
super
end
end
end
alias_method_chain :format_activity_description, :ckeditor
end

View file

@ -0,0 +1,37 @@
module RedmineCkeditor
module Helper
def ckeditor_javascripts
root = RedmineCkeditor.assets_root
plugin_script = RedmineCkeditor.plugins.map {|name|
"CKEDITOR.plugins.addExternal('#{name}', '#{root}/ckeditor-contrib/plugins/#{name}/');"
}.join
javascript_tag("CKEDITOR_BASEPATH = '#{root}/ckeditor/';") +
javascript_include_tag("application", :plugin => "redmine_ckeditor") +
javascript_tag(<<-EOT)
#{plugin_script}
CKEDITOR.on("instanceReady", function(event) {
var editor = event.editor;
var textarea = document.getElementById(editor.name);
editor.on("change", function() {
textarea.value = editor.getSnapshot();
});
});
$(window).on("beforeunload", function() {
for (var id in CKEDITOR.instances) {
if (CKEDITOR.instances[id].checkDirty()) {
return #{l(:text_warn_on_leaving_unsaved).inspect};
}
}
});
$(document).on("submit", "form", function() {
for (var id in CKEDITOR.instances) {
CKEDITOR.instances[id].resetDirty();
}
});
EOT
end
end
end

View file

@ -1,36 +0,0 @@
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

View file

@ -1,11 +0,0 @@
module RedmineCkeditor
module Hooks
class ViewsLayoutsHook < Redmine::Hook::ViewListener
def view_layouts_base_html_head(context={})
return stylesheet_link_tag('/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codesnippet/lib/highlight/styles/default.css', :media => 'all') +
javascript_include_tag('/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codesnippet/lib/highlight/highlight.pack.js') +
javascript_include_tag('inithighlight', :plugin => 'redmine_ckeditor')
end
end
end
end

View file

@ -1,21 +1,8 @@
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
def new
unless RedmineCkeditor.enabled?
new_without_ckeditor
return
return super
end
@journal = Journal.visible.find(params[:journal_id]) if params[:journal_id]
@ -34,7 +21,4 @@ module RedmineCkeditor
render_404
end
end
end
JournalsController.send(:include, JournalsControllerPatch)
end

View file

@ -1,29 +1,18 @@
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)
def cleaned_up_text_body(format = true)
if format
simple_format(super())
else
cleaned_up_text_body_without_ckeditor
super()
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)
def extract_keyword!(text, attr, format=nil)
text = cleaned_up_text_body(false) if RedmineCkeditor.enabled?
super(text, attr, format)
end
end
MailHandler.send(:include, MailHandlerPatch)
end

View file

@ -1,21 +1,8 @@
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
def quote
unless RedmineCkeditor.enabled?
quote_without_ckeditor
return
return super
end
@subject = @message.subject
@ -26,7 +13,4 @@ module RedmineCkeditor
render "quote_with_ckeditor"
end
end
end
MessagesController.send(:include, MessagesControllerPatch)
end

View file

@ -1,31 +1,21 @@
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)
def formatted_text(text)
html = super
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)
def RDMwriteHTMLCell(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)
super
@tmp_images.each do |item|
#logger.info item
File.delete(item) if File.file?(item)
end
end
def get_image_filename_with_ckeditor(attrname)
def get_image_filename(attrname)
img = nil
if attrname.sub!(/^data:([^\/]+)\/([^;]+);base64,/, '')
@ -50,12 +40,12 @@ module RedmineCkeditor
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)
super(attrname)
end
end
img
end
end
Redmine::Export::PDF::ITCPDF.send(:include, PDFPatch)
end
Redmine::Export::PDF::ITCPDF.prepend RedmineCkeditor::PDFPatch

View file

@ -1,13 +1,12 @@
require_dependency 'queries_helper'
module QueriesHelper
def csv_value_with_ckeditor(column, issue, value)
module RedmineCkeditor
module QueriesHelperPatch
def csv_value(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("&nbsp;", " ").strip
else
csv_value_without_ckeditor(column, issue, value)
super
end
end
end
alias_method_chain :csv_value, :ckeditor
end

View file

@ -1,16 +1,6 @@
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)
def thumb_for_file(file)
Redmine::Utils.relative_url_root + if file.simplified_type == "image"
file.rich_file.url(:rich_thumb)
else
@ -18,7 +8,4 @@ module RedmineCkeditor
end
end
end
end
Rich::FilesHelper.send(:include, RichFilesHelperPatch)
end

View file

@ -1,9 +1,11 @@
class Tempfile
def initialize_with_binmode(basename, *rest)
initialize_without_binmode(basename, *rest).tap do |f|
module RedmineCkeditor
module TempfilePatch
def initialize(basename, *rest)
super.tap do |f|
f.binmode if basename == "raw-upload."
end
end
alias_method_chain :initialize, :binmode
end
end
Tempfile.prepend RedmineCkeditor::TempfilePatch

View file

@ -1,28 +1,20 @@
module RedmineCkeditor::WikiFormatting
module Helper
def replace_editor_tag(field_id)
javascript_tag <<-EOT
$(document).ready(function() {
#{replace_editor_script(field_id)}
});
EOT
end
include RedmineCkeditor::Helper
def replace_editor_script(field_id)
def replace_editor_script(field_id, preview_url)
<<-EOT
(function() {
var id = '#{field_id}';
var textarea = document.getElementById(id);
var textarea = document.getElementById('#{field_id}');
if (!textarea) return;
var editor = CKEDITOR.replace(textarea, #{RedmineCkeditor.options(@project).to_json});
editor.on("change", function() { textarea.value = editor.getSnapshot(); });
new jsToolBar(textarea).setPreviewUrl('#{preview_url}');
CKEDITOR.replace(textarea, #{RedmineCkeditor.options(@project).to_json});
})();
EOT
end
def overwrite_functions
javascript_tag <<-EOT
<<-EOT
function showAndScrollTo(id, focus) {
var elem = $("#" + id);
elem.show();
@ -33,21 +25,30 @@ module RedmineCkeditor::WikiFormatting
function destroyEditor(id) {
if (CKEDITOR.instances[id]) CKEDITOR.instances[id].destroy();
}
if (!jsToolBar.prototype._showPreview) {
jsToolBar.prototype._showPreview = jsToolBar.prototype.showPreview
jsToolBar.prototype.showPreview = function(event) {
this._showPreview(event);
$(this.textarea).next().hide();
}
}
if (!jsToolBar.prototype._hidePreview) {
jsToolBar.prototype._hidePreview = jsToolBar.prototype.hidePreview
jsToolBar.prototype.hidePreview = function(event) {
this._hidePreview(event);
$(this.textarea).next().show();
}
}
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
def wikitoolbar_for(field_id, preview_url = preview_text_path)
heads_for_wiki_formatter
script = replace_editor_script(field_id, preview_url)
script += overwrite_functions if request.format.html?
javascript_tag script
end
def initial_page_content(page)
@ -55,6 +56,16 @@ module RedmineCkeditor::WikiFormatting
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/lang/jstoolbar-#{current_language.to_s.downcase}") +
stylesheet_link_tag('jstoolbar') +
ckeditor_javascripts +
stylesheet_link_tag('editor', :plugin => 'redmine_ckeditor')
end
@heads_for_wiki_formatter_included = true
end
end
end
end