From dda045bde9acd76d47c4ae784916dc61bd0ac101 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 30 Nov 2020 11:19:32 +0100 Subject: [PATCH] Actualizar plugin CKEditor a 1.2.3 --- plugins/redmine_ckeditor/.gitmodules | 3 + plugins/redmine_ckeditor/Gemfile | 6 +- plugins/redmine_ckeditor/README.rdoc | 10 +- .../ckeditor-contrib/skins/moono/skin.js | 316 ++++++++++++++++++ .../redmine_ckeditor/config/locales/pt.yml | 15 + ...0418001207_create_rich_rich_images.rich.rb | 2 +- ...001208_add_uri_cache_to_rich_image.rich.rb | 2 +- ...30418001209_refactor_image_to_file.rich.rb | 2 +- plugins/redmine_ckeditor/init.rb | 8 +- .../rich_assets/rich_assets_generator.rb | 1 + .../redmine_ckeditor/lib/redmine_ckeditor.rb | 21 +- .../application_helper_patch.rb | 27 +- .../lib/redmine_ckeditor/helper.rb | 37 ++ .../hooks/journal_listener.rb | 36 -- .../hooks/views_layouts_hook.rb | 11 - .../journals_controller_patch.rb | 48 +-- .../redmine_ckeditor/mail_handler_patch.rb | 25 +- .../messages_controller_patch.rb | 32 +- .../lib/redmine_ckeditor/pdf_patch.rb | 26 +- .../redmine_ckeditor/queries_helper_patch.rb | 19 +- .../rich_files_helper_patch.rb | 23 +- .../lib/redmine_ckeditor/tempfile_patch.rb | 14 +- .../wiki_formatting/helper.rb | 69 ++-- 23 files changed, 513 insertions(+), 240 deletions(-) create mode 100644 plugins/redmine_ckeditor/.gitmodules create mode 100644 plugins/redmine_ckeditor/assets/ckeditor-contrib/skins/moono/skin.js create mode 100644 plugins/redmine_ckeditor/config/locales/pt.yml create mode 100644 plugins/redmine_ckeditor/lib/redmine_ckeditor/helper.rb delete mode 100644 plugins/redmine_ckeditor/lib/redmine_ckeditor/hooks/journal_listener.rb delete mode 100644 plugins/redmine_ckeditor/lib/redmine_ckeditor/hooks/views_layouts_hook.rb diff --git a/plugins/redmine_ckeditor/.gitmodules b/plugins/redmine_ckeditor/.gitmodules new file mode 100644 index 0000000..de30e75 --- /dev/null +++ b/plugins/redmine_ckeditor/.gitmodules @@ -0,0 +1,3 @@ +[submodule "app/assets/javascripts/ckeditor-releases"] + path = app/assets/javascripts/ckeditor-releases + url = git://github.com/ckeditor/ckeditor-releases.git diff --git a/plugins/redmine_ckeditor/Gemfile b/plugins/redmine_ckeditor/Gemfile index d7903df..74e5561 100644 --- a/plugins/redmine_ckeditor/Gemfile +++ b/plugins/redmine_ckeditor/Gemfile @@ -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 diff --git a/plugins/redmine_ckeditor/README.rdoc b/plugins/redmine_ckeditor/README.rdoc index f52092c..ca5c032 100644 --- a/plugins/redmine_ckeditor/README.rdoc +++ b/plugins/redmine_ckeditor/README.rdoc @@ -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) diff --git a/plugins/redmine_ckeditor/assets/ckeditor-contrib/skins/moono/skin.js b/plugins/redmine_ckeditor/assets/ckeditor-contrib/skins/moono/skin.js new file mode 100644 index 0000000..cd588a4 --- /dev/null +++ b/plugins/redmine_ckeditor/assets/ckeditor-contrib/skins/moono/skin.js @@ -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% diff --git a/plugins/redmine_ckeditor/config/locales/pt.yml b/plugins/redmine_ckeditor/config/locales/pt.yml new file mode 100644 index 0000000..6aaf7a1 --- /dev/null +++ b/plugins/redmine_ckeditor/config/locales/pt.yml @@ -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 diff --git a/plugins/redmine_ckeditor/db/migrate/20130418001207_create_rich_rich_images.rich.rb b/plugins/redmine_ckeditor/db/migrate/20130418001207_create_rich_rich_images.rich.rb index 64051d3..b3ffefb 100644 --- a/plugins/redmine_ckeditor/db/migrate/20130418001207_create_rich_rich_images.rich.rb +++ b/plugins/redmine_ckeditor/db/migrate/20130418001207_create_rich_rich_images.rich.rb @@ -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| diff --git a/plugins/redmine_ckeditor/db/migrate/20130418001208_add_uri_cache_to_rich_image.rich.rb b/plugins/redmine_ckeditor/db/migrate/20130418001208_add_uri_cache_to_rich_image.rich.rb index 4424857..35ad1d1 100644 --- a/plugins/redmine_ckeditor/db/migrate/20130418001208_add_uri_cache_to_rich_image.rich.rb +++ b/plugins/redmine_ckeditor/db/migrate/20130418001208_add_uri_cache_to_rich_image.rich.rb @@ -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 diff --git a/plugins/redmine_ckeditor/db/migrate/20130418001209_refactor_image_to_file.rich.rb b/plugins/redmine_ckeditor/db/migrate/20130418001209_refactor_image_to_file.rich.rb index 7d61ad5..9fa597e 100644 --- a/plugins/redmine_ckeditor/db/migrate/20130418001209_refactor_image_to_file.rich.rb +++ b/plugins/redmine_ckeditor/db/migrate/20130418001209_refactor_image_to_file.rich.rb @@ -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 diff --git a/plugins/redmine_ckeditor/init.rb b/plugins/redmine_ckeditor/init.rb index 8583b4f..0b4a1b8 100644 --- a/plugins/redmine_ckeditor/init.rb +++ b/plugins/redmine_ckeditor/init.rb @@ -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 diff --git a/plugins/redmine_ckeditor/lib/generators/redmine_ckeditor/rich_assets/rich_assets_generator.rb b/plugins/redmine_ckeditor/lib/generators/redmine_ckeditor/rich_assets/rich_assets_generator.rb index 4aad050..03e45cd 100644 --- a/plugins/redmine_ckeditor/lib/generators/redmine_ckeditor/rich_assets/rich_assets_generator.rb +++ b/plugins/redmine_ckeditor/lib/generators/redmine_ckeditor/rich_assets/rich_assets_generator.rb @@ -1,4 +1,5 @@ require 'rake' +require 'rails/generators' module RedmineCkeditor class RichAssetsGenerator < Rails::Generators::Base diff --git a/plugins/redmine_ckeditor/lib/redmine_ckeditor.rb b/plugins/redmine_ckeditor/lib/redmine_ckeditor.rb index 49b1f55..54de23a 100644 --- a/plugins/redmine_ckeditor/lib/redmine_ckeditor.rb +++ b/plugins/redmine_ckeditor/lib/redmine_ckeditor.rb @@ -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' diff --git a/plugins/redmine_ckeditor/lib/redmine_ckeditor/application_helper_patch.rb b/plugins/redmine_ckeditor/lib/redmine_ckeditor/application_helper_patch.rb index 7117106..79ae7a2 100644 --- a/plugins/redmine_ckeditor/lib/redmine_ckeditor/application_helper_patch.rb +++ b/plugins/redmine_ckeditor/lib/redmine_ckeditor/application_helper_patch.rb @@ -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) - if RedmineCkeditor.enabled? - simple_format(truncate(HTMLEntities.new.decode(strip_tags(text.to_s)), :length => 120)) - else - format_activity_description_without_ckeditor(text) + def format_activity_description(text) + if RedmineCkeditor.enabled? + simple_format(truncate(HTMLEntities.new.decode(strip_tags(text.to_s)), :length => 120)) + else + super + end end end - alias_method_chain :format_activity_description, :ckeditor end diff --git a/plugins/redmine_ckeditor/lib/redmine_ckeditor/helper.rb b/plugins/redmine_ckeditor/lib/redmine_ckeditor/helper.rb new file mode 100644 index 0000000..29c27a5 --- /dev/null +++ b/plugins/redmine_ckeditor/lib/redmine_ckeditor/helper.rb @@ -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 diff --git a/plugins/redmine_ckeditor/lib/redmine_ckeditor/hooks/journal_listener.rb b/plugins/redmine_ckeditor/lib/redmine_ckeditor/hooks/journal_listener.rb deleted file mode 100644 index 182ddea..0000000 --- a/plugins/redmine_ckeditor/lib/redmine_ckeditor/hooks/journal_listener.rb +++ /dev/null @@ -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 - diff --git a/plugins/redmine_ckeditor/lib/redmine_ckeditor/hooks/views_layouts_hook.rb b/plugins/redmine_ckeditor/lib/redmine_ckeditor/hooks/views_layouts_hook.rb deleted file mode 100644 index eef5687..0000000 --- a/plugins/redmine_ckeditor/lib/redmine_ckeditor/hooks/views_layouts_hook.rb +++ /dev/null @@ -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 diff --git a/plugins/redmine_ckeditor/lib/redmine_ckeditor/journals_controller_patch.rb b/plugins/redmine_ckeditor/lib/redmine_ckeditor/journals_controller_patch.rb index 8656c37..601eb40 100644 --- a/plugins/redmine_ckeditor/lib/redmine_ckeditor/journals_controller_patch.rb +++ b/plugins/redmine_ckeditor/lib/redmine_ckeditor/journals_controller_patch.rb @@ -1,40 +1,24 @@ -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 + def new + unless RedmineCkeditor.enabled? + return super 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 = "

#{ll(I18n.locale, :text_user_wrote, user)}

" - @content << "
#{text}

" - - render "new_with_ckeditor" - rescue ActiveRecord::RecordNotFound - render_404 + @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 = "

#{ll(I18n.locale, :text_user_wrote, user)}

" + @content << "
#{text}

" + + render "new_with_ckeditor" + rescue ActiveRecord::RecordNotFound + render_404 end end - - JournalsController.send(:include, JournalsControllerPatch) end diff --git a/plugins/redmine_ckeditor/lib/redmine_ckeditor/mail_handler_patch.rb b/plugins/redmine_ckeditor/lib/redmine_ckeditor/mail_handler_patch.rb index bc3ddac..9380728 100644 --- a/plugins/redmine_ckeditor/lib/redmine_ckeditor/mail_handler_patch.rb +++ b/plugins/redmine_ckeditor/lib/redmine_ckeditor/mail_handler_patch.rb @@ -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 diff --git a/plugins/redmine_ckeditor/lib/redmine_ckeditor/messages_controller_patch.rb b/plugins/redmine_ckeditor/lib/redmine_ckeditor/messages_controller_patch.rb index aa0c73c..09f40a3 100644 --- a/plugins/redmine_ckeditor/lib/redmine_ckeditor/messages_controller_patch.rb +++ b/plugins/redmine_ckeditor/lib/redmine_ckeditor/messages_controller_patch.rb @@ -1,32 +1,16 @@ -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 + def quote + unless RedmineCkeditor.enabled? + return super 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 = "

#{ll(I18n.locale, :text_user_wrote, @message.author)}

" + @content << "
#{ActionView::Base.full_sanitizer.sanitize(@message.content.to_s)}

" - @subject = @message.subject - @subject = "RE: #{@subject}" unless @subject.starts_with?('RE:') - @content = "

#{ll(I18n.locale, :text_user_wrote, @message.author)}

" - @content << "
#{ActionView::Base.full_sanitizer.sanitize(@message.content.to_s)}

" - - render "quote_with_ckeditor" - end + render "quote_with_ckeditor" end end - - MessagesController.send(:include, MessagesControllerPatch) end diff --git a/plugins/redmine_ckeditor/lib/redmine_ckeditor/pdf_patch.rb b/plugins/redmine_ckeditor/lib/redmine_ckeditor/pdf_patch.rb index ae7d886..2ebd10f 100644 --- a/plugins/redmine_ckeditor/lib/redmine_ckeditor/pdf_patch.rb +++ b/plugins/redmine_ckeditor/lib/redmine_ckeditor/pdf_patch.rb @@ -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 diff --git a/plugins/redmine_ckeditor/lib/redmine_ckeditor/queries_helper_patch.rb b/plugins/redmine_ckeditor/lib/redmine_ckeditor/queries_helper_patch.rb index bd8bdb6..3917e26 100644 --- a/plugins/redmine_ckeditor/lib/redmine_ckeditor/queries_helper_patch.rb +++ b/plugins/redmine_ckeditor/lib/redmine_ckeditor/queries_helper_patch.rb @@ -1,13 +1,12 @@ -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) +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(" ", " ").strip + else + super + end end end - alias_method_chain :csv_value, :ckeditor end diff --git a/plugins/redmine_ckeditor/lib/redmine_ckeditor/rich_files_helper_patch.rb b/plugins/redmine_ckeditor/lib/redmine_ckeditor/rich_files_helper_patch.rb index 76838de..e0ca9e0 100644 --- a/plugins/redmine_ckeditor/lib/redmine_ckeditor/rich_files_helper_patch.rb +++ b/plugins/redmine_ckeditor/lib/redmine_ckeditor/rich_files_helper_patch.rb @@ -1,24 +1,11 @@ -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 + def thumb_for_file(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 - - Rich::FilesHelper.send(:include, RichFilesHelperPatch) end diff --git a/plugins/redmine_ckeditor/lib/redmine_ckeditor/tempfile_patch.rb b/plugins/redmine_ckeditor/lib/redmine_ckeditor/tempfile_patch.rb index 14d9a13..ea3403d 100755 --- a/plugins/redmine_ckeditor/lib/redmine_ckeditor/tempfile_patch.rb +++ b/plugins/redmine_ckeditor/lib/redmine_ckeditor/tempfile_patch.rb @@ -1,9 +1,11 @@ -class Tempfile - def initialize_with_binmode(basename, *rest) - initialize_without_binmode(basename, *rest).tap do |f| - f.binmode if basename == "raw-upload." +module RedmineCkeditor + module TempfilePatch + def initialize(basename, *rest) + super.tap do |f| + f.binmode if basename == "raw-upload." + end end end - - alias_method_chain :initialize, :binmode end + +Tempfile.prepend RedmineCkeditor::TempfilePatch diff --git a/plugins/redmine_ckeditor/lib/redmine_ckeditor/wiki_formatting/helper.rb b/plugins/redmine_ckeditor/lib/redmine_ckeditor/wiki_formatting/helper.rb index ff4b0e0..6d79596 100644 --- a/plugins/redmine_ckeditor/lib/redmine_ckeditor/wiki_formatting/helper.rb +++ b/plugins/redmine_ckeditor/lib/redmine_ckeditor/wiki_formatting/helper.rb @@ -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); - if (!textarea) return; - - var editor = CKEDITOR.replace(textarea, #{RedmineCkeditor.options(@project).to_json}); - editor.on("change", function() { textarea.value = editor.getSnapshot(); }); - })(); + (function() { + var textarea = document.getElementById('#{field_id}'); + if (!textarea) return; + 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