diff options
-rw-r--r-- | lib/redcloth3.rb | 15 | ||||
-rw-r--r-- | lib/redmine/wiki_formatting/textile/formatter.rb | 2 | ||||
-rw-r--r-- | test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb | 44 |
3 files changed, 59 insertions, 2 deletions
diff --git a/lib/redcloth3.rb b/lib/redcloth3.rb index d09804f41..e15970822 100644 --- a/lib/redcloth3.rb +++ b/lib/redcloth3.rb @@ -474,7 +474,10 @@ class RedCloth3 < String style << "vertical-align:#{ v_align( $& ) };" if text =~ A_VLGN end - style << "#{ htmlesc $1 };" if text.sub!( /\{([^}]*)\}/, '' ) && !filter_styles + if text.sub!( /\{([^"}]*)\}/, '' ) && !filter_styles + sanitized = sanitize_styles($1) + style << "#{ sanitized };" unless sanitized.blank? + end lang = $1 if text.sub!( /\[([^)]+?)\]/, '' ) @@ -502,6 +505,16 @@ class RedCloth3 < String atts end + STYLES_RE = /^(color|width|height|border|background|padding|margin|font|text)(-[a-z]+)*:\s*((\d+%?|\d+px|\d+(\.\d+)?em|#[0-9a-f]+|[a-z]+)\s*)+$/i + + def sanitize_styles(str) + styles = str.split(";").map(&:strip) + styles.reject! do |style| + !style.match(STYLES_RE) + end + styles.join(";") + end + TABLE_RE = /^(?:table(_?#{S}#{A}#{C})\. ?\n)?^(#{A}#{C}\.? ?\|.*?\|)(\n\n|\Z)/m # Parses a Textile table block, building HTML from the result. diff --git a/lib/redmine/wiki_formatting/textile/formatter.rb b/lib/redmine/wiki_formatting/textile/formatter.rb index 22cd5cbf9..bbe47a15c 100644 --- a/lib/redmine/wiki_formatting/textile/formatter.rb +++ b/lib/redmine/wiki_formatting/textile/formatter.rb @@ -31,7 +31,7 @@ module Redmine super self.hard_breaks=true self.no_span_caps=true - self.filter_styles=true + self.filter_styles=false end def to_html(*rules) diff --git a/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb b/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb index 26250997e..ce4feb62a 100644 --- a/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb +++ b/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb @@ -59,6 +59,50 @@ class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase end end + def test_styles + # single style + assert_html_output({ + 'p{color:red}. text' => '<p style="color:red;">text</p>', + 'p{color:red;}. text' => '<p style="color:red;">text</p>', + 'p{color: red}. text' => '<p style="color: red;">text</p>', + 'p{color:#f00}. text' => '<p style="color:#f00;">text</p>', + 'p{color:#ff0000}. text' => '<p style="color:#ff0000;">text</p>', + 'p{border:10px}. text' => '<p style="border:10px;">text</p>', + 'p{border:10}. text' => '<p style="border:10;">text</p>', + 'p{border:10%}. text' => '<p style="border:10%;">text</p>', + 'p{border:10em}. text' => '<p style="border:10em;">text</p>', + 'p{border:1.5em}. text' => '<p style="border:1.5em;">text</p>', + 'p{border-left:1px}. text' => '<p style="border-left:1px;">text</p>', + 'p{border-right:1px}. text' => '<p style="border-right:1px;">text</p>', + 'p{border-top:1px}. text' => '<p style="border-top:1px;">text</p>', + 'p{border-bottom:1px}. text' => '<p style="border-bottom:1px;">text</p>', + }, false) + + # multiple styles + assert_html_output({ + 'p{color:red; border-top:1px}. text' => '<p style="color:red;border-top:1px;">text</p>', + 'p{color:red ; border-top:1px}. text' => '<p style="color:red;border-top:1px;">text</p>', + 'p{color:red;border-top:1px}. text' => '<p style="color:red;border-top:1px;">text</p>', + }, false) + + # styles with multiple values + assert_html_output({ + 'p{border:1px solid red;}. text' => '<p style="border:1px solid red;">text</p>', + 'p{border-top-left-radius: 10px 5px;}. text' => '<p style="border-top-left-radius: 10px 5px;">text</p>', + }, false) + end + + def test_invalid_styles_should_be_filtered + assert_html_output({ + 'p{invalid}. text' => '<p>text</p>', + 'p{invalid:red}. text' => '<p>text</p>', + 'p{color:(red)}. text' => '<p>text</p>', + 'p{color:red;invalid:blue}. text' => '<p style="color:red;">text</p>', + 'p{invalid:blue;color:red}. text' => '<p style="color:red;">text</p>', + 'p{color:"}. text' => '<p>text</p>', + }, false) + end + def test_inline_code assert_html_output( 'this is @some code@' => 'this is <code>some code</code>', |