From 2ad8242ae782ea9d87a0d98f8563199da736bdc7 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sat, 6 Feb 2010 10:40:21 +0000 Subject: [PATCH] Adds a setting to cache textile rendering (off by default). * it uses ActionController cache store which is MemoryStore by default and can be configured with config.action_controller.cache_store * macro processing was moved out of textile rendering so that it doesn't get cached * no noticeable improvement is expected for small portions of text, so only texts larger than 2KB are cached git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@3372 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/application_helper.rb | 5 +- app/views/settings/_general.rhtml | 2 + config/environment.rb | 2 +- config/locales/bg.yml | 1 + config/locales/bs.yml | 1 + config/locales/ca.yml | 1 + config/locales/cs.yml | 1 + config/locales/da.yml | 1 + config/locales/de.yml | 1 + config/locales/el.yml | 1 + config/locales/en.yml | 1 + config/locales/es.yml | 1 + config/locales/eu.yml | 1 + config/locales/fi.yml | 1 + config/locales/fr.yml | 1 + config/locales/gl.yml | 1 + config/locales/he.yml | 1 + config/locales/hr.yml | 1 + config/locales/hu.yml | 1 + config/locales/id.yml | 1 + config/locales/it.yml | 1 + config/locales/ja.yml | 1 + config/locales/ko.yml | 1 + config/locales/lt.yml | 1 + config/locales/nl.yml | 1 + config/locales/no.yml | 1 + config/locales/pl.yml | 1 + config/locales/pt-BR.yml | 1 + config/locales/pt.yml | 1 + config/locales/ro.yml | 1 + config/locales/ru.yml | 1 + config/locales/sk.yml | 1 + config/locales/sl.yml | 1 + config/locales/sr.yml | 1 + config/locales/sv.yml | 1 + config/locales/th.yml | 1 + config/locales/tr.yml | 1 + config/locales/uk.yml | 1 + config/locales/vi.yml | 1 + config/locales/zh-TW.yml | 1 + config/locales/zh.yml | 1 + config/settings.yml | 2 + lib/redmine/wiki_formatting.rb | 53 ++++++++++++++++++- .../wiki_formatting/textile/formatter.rb | 31 +---------- 44 files changed, 100 insertions(+), 33 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index c6f743dd4..02db2caf5 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -396,13 +396,14 @@ module ApplicationHelper text = args.shift when 2 obj = args.shift - text = obj.send(args.shift).to_s + attr = args.shift + text = obj.send(attr).to_s else raise ArgumentError, 'invalid arguments to textilizable' end return '' if text.blank? - text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text) { |macro, args| exec_macro(macro, obj, args) } + text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) { |macro, args| exec_macro(macro, obj, args) } only_path = options.delete(:only_path) == false ? false : true diff --git a/app/views/settings/_general.rhtml b/app/views/settings/_general.rhtml index ff0dde357..a2f014528 100644 --- a/app/views/settings/_general.rhtml +++ b/app/views/settings/_general.rhtml @@ -20,6 +20,8 @@

<%= setting_select :text_formatting, Redmine::WikiFormatting.format_names.collect{|name| [name, name.to_s]}, :blank => :label_none %>

+

<%= setting_check_box :cache_formatted_text %>

+

<%= setting_select :wiki_compression, [['Gzip', 'gzip']], :blank => :label_none %>

<%= setting_text_field :feeds_limit, :size => 6 %>

diff --git a/config/environment.rb b/config/environment.rb index 97fc54adb..f89695f46 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -32,7 +32,7 @@ Rails::Initializer.run do |config| # Enable page/fragment caching by setting a file-based store # (remember to create the caching directory and make it readable to the application) - # config.action_controller.fragment_cache_store = :file_store, "#{RAILS_ROOT}/cache" + # config.action_controller.cache_store = :file_store, "#{RAILS_ROOT}/tmp/cache" # Activate observers that should always be running # config.active_record.observers = :cacher, :garbage_collector diff --git a/config/locales/bg.yml b/config/locales/bg.yml index d48c09314..6e87d6006 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -879,3 +879,4 @@ bg: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/bs.yml b/config/locales/bs.yml index 6d297fefe..54d6589cf 100644 --- a/config/locales/bs.yml +++ b/config/locales/bs.yml @@ -903,3 +903,4 @@ bs: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/ca.yml b/config/locales/ca.yml index dc033a24e..878cb1ee2 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -882,3 +882,4 @@ ca: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/cs.yml b/config/locales/cs.yml index dd4cea30b..5ca186bc2 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -885,3 +885,4 @@ cs: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/da.yml b/config/locales/da.yml index 1da8ac2fc..cdee28158 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -905,3 +905,4 @@ da: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/de.yml b/config/locales/de.yml index ddb292c5d..f8a7c9f5c 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -905,3 +905,4 @@ de: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/el.yml b/config/locales/el.yml index 3943cb5c3..c5d4f15a6 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -885,3 +885,4 @@ el: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/en.yml b/config/locales/en.yml index c8b0ddbee..8109e5731 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -329,6 +329,7 @@ en: setting_issue_done_ratio_issue_status: Use the issue status setting_start_of_week: Start calendars on setting_rest_api_enabled: Enable REST web service + setting_cache_formatted_text: Cache formatted text permission_add_project: Create project permission_add_subprojects: Create subprojects diff --git a/config/locales/es.yml b/config/locales/es.yml index 8bc7c8c18..b34bfdb75 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -929,3 +929,4 @@ es: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/eu.yml b/config/locales/eu.yml index 04bb5c5b7..35408067e 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -889,3 +889,4 @@ eu: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/fi.yml b/config/locales/fi.yml index 9ed111556..3a7cbea65 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -915,3 +915,4 @@ fi: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 99c4361f0..663b6f703 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -352,6 +352,7 @@ fr: setting_rest_api_enabled: Activer l'API REST setting_gravatar_default: Image Gravatar par défaut setting_start_of_week: Jour de début des calendriers + setting_cache_formatted_text: Mettre en cache le texte formaté permission_add_project: Créer un projet permission_add_subprojects: Créer des sous-projets diff --git a/config/locales/gl.yml b/config/locales/gl.yml index b606ad46d..deb85638f 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -905,3 +905,4 @@ gl: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/he.yml b/config/locales/he.yml index c2604ee50..1e2ecc68b 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -889,3 +889,4 @@ he: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/hr.yml b/config/locales/hr.yml index 4244e5b6c..7ee3deff8 100644 --- a/config/locales/hr.yml +++ b/config/locales/hr.yml @@ -892,3 +892,4 @@ hr: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/hu.yml b/config/locales/hu.yml index f419aa301..7fac563ef 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -910,3 +910,4 @@ label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/id.yml b/config/locales/id.yml index db92948ae..cf63d733a 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -897,3 +897,4 @@ id: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/it.yml b/config/locales/it.yml index a3c12ad3f..334e88597 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -892,3 +892,4 @@ it: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 4a0fb8941..69a8c09eb 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -914,3 +914,4 @@ ja: enumeration_activities: 作業分類 (時間トラッキング) enumeration_system_activity: システム作業分類 permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 99fc180b3..0edb2b546 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -945,3 +945,4 @@ ko: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/lt.yml b/config/locales/lt.yml index 43158bcca..e49c09f22 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -953,3 +953,4 @@ lt: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 024db3238..a5f69b3b4 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -867,3 +867,4 @@ nl: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/no.yml b/config/locales/no.yml index 726dadb46..39c54a9f4 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -880,3 +880,4 @@ label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 5d4e62e55..40605bbac 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -910,3 +910,4 @@ pl: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 53f968ad1..17647e45d 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -913,3 +913,4 @@ pt-BR: label_board_locked: Travado label_change_log: Registro de alterações permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 5d9d8ce46..6a25981ae 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -897,3 +897,4 @@ pt: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/ro.yml b/config/locales/ro.yml index 257cf8e19..bfefe5180 100644 --- a/config/locales/ro.yml +++ b/config/locales/ro.yml @@ -882,3 +882,4 @@ ro: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 2dd495212..5821f0ba3 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -993,3 +993,4 @@ ru: label_board_sticky: Прикреплена label_board_locked: Заблокирована permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/sk.yml b/config/locales/sk.yml index c1070ab16..ce86fc33f 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -884,3 +884,4 @@ sk: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/sl.yml b/config/locales/sl.yml index b12c77d78..7967deeab 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -881,3 +881,4 @@ sl: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/sr.yml b/config/locales/sr.yml index 28eaaaa3c..6b8c7ed31 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -900,3 +900,4 @@ label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/sv.yml b/config/locales/sv.yml index d0488ad96..cca36ec83 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -934,3 +934,4 @@ sv: enumeration_activities: Aktiviteter (tidsuppföljning) enumeration_system_activity: Systemaktivitet permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/th.yml b/config/locales/th.yml index c5982851f..35461ab15 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -882,3 +882,4 @@ th: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 86b365d85..482dcfa5e 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -912,3 +912,4 @@ tr: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/uk.yml b/config/locales/uk.yml index 4ae064d69..f813559bc 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -881,3 +881,4 @@ uk: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/vi.yml b/config/locales/vi.yml index c66cdd53b..a359ed230 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -944,3 +944,4 @@ vi: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index db5bfa2e8..28aedbc62 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -976,3 +976,4 @@ enumeration_activities: 活動 (時間追蹤) enumeration_system_activity: 系統活動 permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/locales/zh.yml b/config/locales/zh.yml index 8e7dc4d1c..50f486783 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -907,3 +907,4 @@ zh: label_board_sticky: Sticky label_board_locked: Locked permission_export_wiki_pages: Export wiki pages + setting_cache_formatted_text: Cache formatted text diff --git a/config/settings.yml b/config/settings.yml index cebfbb500..1e905ede3 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -53,6 +53,8 @@ plain_text_mail: default: 0 text_formatting: default: textile +cache_formatted_text: + default: 0 wiki_compression: default: "" default_language: diff --git a/lib/redmine/wiki_formatting.rb b/lib/redmine/wiki_formatting.rb index f33ef9e6d..21e8be66b 100644 --- a/lib/redmine/wiki_formatting.rb +++ b/lib/redmine/wiki_formatting.rb @@ -44,7 +44,58 @@ module Redmine end def to_html(format, text, options = {}, &block) - formatter_for(format).new(text).to_html(&block) + text = if Setting.cache_formatted_text? && text.size > 2.kilobyte && cache && cache_key = cache_key_for(format, options[:object], options[:attribute]) + # Text retrieved from the cache store may be frozen + # We need to dup it so we can do in-place substitutions with gsub! + cache.fetch cache_key do + formatter_for(format).new(text).to_html + end.dup + else + formatter_for(format).new(text).to_html + end + if block_given? + execute_macros(text, block) + end + text + end + + # Returns a cache key for the given text +format+, +object+ and +attribute+ or nil if no caching should be done + def cache_key_for(format, object, attribute) + if object && attribute && !object.new_record? && object.respond_to?(:updated_on) && !format.blank? + "formatted_text/#{format}/#{object.class.model_name.cache_key}/#{object.id}-#{attribute}-#{object.updated_on.to_s(:number)}" + end + end + + # Returns the cache store used to cache HTML output + def cache + ActionController::Base.cache_store + end + + MACROS_RE = / + (!)? # escaping + ( + \{\{ # opening tag + ([\w]+) # macro name + (\(([^\}]*)\))? # optional arguments + \}\} # closing tag + ) + /x unless const_defined?(:MACROS_RE) + + # Macros substitution + def execute_macros(text, macros_runner) + text.gsub!(MACROS_RE) do + esc, all, macro = $1, $2, $3.downcase + args = ($5 || '').split(',').each(&:strip) + if esc.nil? + begin + macros_runner.call(macro, args) + rescue => e + "
Error executing the #{macro} macro (#{e})
" + end || all + else + all + end + end end end diff --git a/lib/redmine/wiki_formatting/textile/formatter.rb b/lib/redmine/wiki_formatting/textile/formatter.rb index 7e20c7bfc..ab66ba5b7 100644 --- a/lib/redmine/wiki_formatting/textile/formatter.rb +++ b/lib/redmine/wiki_formatting/textile/formatter.rb @@ -24,7 +24,7 @@ module Redmine class Formatter < RedCloth3 # auto_link rule after textile rules so that it doesn't break !image_url! tags - RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto, :inline_toc, :inline_macros] + RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto, :inline_toc] def initialize(*args) super @@ -33,9 +33,8 @@ module Redmine self.filter_styles=true end - def to_html(*rules, &block) + def to_html(*rules) @toc = [] - @macros_runner = block super(*RULES).to_s end @@ -102,32 +101,6 @@ module Redmine end end - MACROS_RE = / - (!)? # escaping - ( - \{\{ # opening tag - ([\w]+) # macro name - (\(([^\}]*)\))? # optional arguments - \}\} # closing tag - ) - /x unless const_defined?(:MACROS_RE) - - def inline_macros(text) - text.gsub!(MACROS_RE) do - esc, all, macro = $1, $2, $3.downcase - args = ($5 || '').split(',').each(&:strip) - if esc.nil? - begin - @macros_runner.call(macro, args) - rescue => e - "
Error executing the #{macro} macro (#{e})
" - end || all - else - all - end - end - end - AUTO_LINK_RE = %r{ ( # leading text <\w+.*?>| # leading HTML tag, or -- 2.39.5