0001-Remove-unnecessary-trailing-white-spaces.patch

Yuichi HARADA, 2019-03-28 05:18

Download (23.6 KB)

View differences:

lib/redmine/wiki_formatting/textile/redcloth3.rb
73 73
#
74 74
# == Links
75 75
#
76
# To make a hypertext link, put the link text in "quotation 
76
# To make a hypertext link, put the link text in "quotation
77 77
# marks" followed immediately by a colon and the URL of the link.
78
# 
79
# Optional: text in (parentheses) following the link text, 
80
# but before the closing quotation mark, will become a Title 
78
#
79
# Optional: text in (parentheses) following the link text,
80
# but before the closing quotation mark, will become a Title
81 81
# attribute for the link, visible as a tool tip when a cursor is above it.
82
# 
82
#
83 83
# Example:
84 84
#
85 85
#  "This is a link (This is a title) ":http://www.textism.com
86
# 
86
#
87 87
# Will become:
88
# 
88
#
89 89
#  <a href="http://www.textism.com" title="This is a title">This is a link</a>
90 90
#
91 91
# == Images
92 92
#
93 93
# To insert an image, put the URL for the image inside exclamation marks.
94 94
#
95
# Optional: text that immediately follows the URL in (parentheses) will 
96
# be used as the Alt text for the image. Images on the web should always 
97
# have descriptive Alt text for the benefit of readers using non-graphical 
95
# Optional: text that immediately follows the URL in (parentheses) will
96
# be used as the Alt text for the image. Images on the web should always
97
# have descriptive Alt text for the benefit of readers using non-graphical
98 98
# browsers.
99 99
#
100
# Optional: place a colon followed by a URL immediately after the 
100
# Optional: place a colon followed by a URL immediately after the
101 101
# closing ! to make the image into a link.
102
# 
102
#
103 103
# Example:
104 104
#
105 105
#  !http://www.textism.com/common/textist.gif(Textist)!
......
118 118
#
119 119
# == Defining Acronyms
120 120
#
121
# HTML allows authors to define acronyms via the tag. The definition appears as a 
122
# tool tip when a cursor hovers over the acronym. A crucial aid to clear writing, 
121
# HTML allows authors to define acronyms via the tag. The definition appears as a
122
# tool tip when a cursor hovers over the acronym. A crucial aid to clear writing,
123 123
# this should be used at least once for each acronym in documents where they appear.
124 124
#
125
# To quickly define an acronym in Textile, place the full text in (parentheses) 
125
# To quickly define an acronym in Textile, place the full text in (parentheses)
126 126
# immediately following the acronym.
127
# 
127
#
128 128
# Example:
129 129
#
130 130
#  ACLU(American Civil Liberties Union)
......
147 147
#     (background:#ddd;color:red). |{}| | | |
148 148
#
149 149
# == Using RedCloth
150
# 
150
#
151 151
# RedCloth is simply an extension of the String class, which can handle
152 152
# Textile formatting.  Use it like a String and output HTML with its
153 153
# RedCloth#to_html method.
......
270 270
        rules = DEFAULT_RULES if rules.empty?
271 271
        # make our working copy
272 272
        text = self.dup
273
        
273

  
274 274
        @urlrefs = {}
275 275
        @shelf = []
276 276
        textile_rules = [:block_textile_table, :block_textile_lists,
277 277
                         :block_textile_prefix, :inline_textile_image, :inline_textile_code,
278 278
                         :inline_textile_span, :inline_textile_link, :glyphs_textile]
279 279
        markdown_rules = [:refs_markdown, :block_markdown_setext, :block_markdown_atx, :block_markdown_rule,
280
                          :block_markdown_bq, :block_markdown_lists, 
280
                          :block_markdown_bq, :block_markdown_lists,
281 281
                          :inline_markdown_reflink, :inline_markdown_link]
282 282
        @rules = rules.collect do |rule|
283 283
            case rule
......
291 291
        end.flatten
292 292

  
293 293
        # standard clean up
294
        incoming_entities text 
295
        clean_white_space text 
294
        incoming_entities text
295
        clean_white_space text
296 296

  
297 297
        # start processor
298 298
        @pre_list = []
......
301 301
        escape_html_tags text
302 302
        # need to do this before #hard_break and #blocks
303 303
        block_textile_quotes text unless @lite_mode
304
        hard_break text 
304
        hard_break text
305 305
        unless @lite_mode
306 306
            refs text
307 307
            blocks text
......
328 328
    #
329 329
    TEXTILE_TAGS =
330 330

  
331
        [[128, 8364], [129, 0], [130, 8218], [131, 402], [132, 8222], [133, 8230], 
332
         [134, 8224], [135, 8225], [136, 710], [137, 8240], [138, 352], [139, 8249], 
333
         [140, 338], [141, 0], [142, 0], [143, 0], [144, 0], [145, 8216], [146, 8217], 
334
         [147, 8220], [148, 8221], [149, 8226], [150, 8211], [151, 8212], [152, 732], 
331
        [[128, 8364], [129, 0], [130, 8218], [131, 402], [132, 8222], [133, 8230],
332
         [134, 8224], [135, 8225], [136, 710], [137, 8240], [138, 352], [139, 8249],
333
         [140, 338], [141, 0], [142, 0], [143, 0], [144, 0], [145, 8216], [146, 8217],
334
         [147, 8220], [148, 8221], [149, 8226], [150, 8211], [151, 8212], [152, 732],
335 335
         [153, 8482], [154, 353], [155, 8250], [156, 339], [157, 0], [158, 0], [159, 376]].
336 336

  
337 337
        collect! do |a, b|
......
359 359

  
360 360
    # Text markup tags, don't conflict with block tags
361 361
    SIMPLE_HTML_TAGS = [
362
        'tt', 'b', 'i', 'big', 'small', 'em', 'strong', 'dfn', 'code', 
362
        'tt', 'b', 'i', 'big', 'small', 'em', 'strong', 'dfn', 'code',
363 363
        'samp', 'kbd', 'var', 'cite', 'abbr', 'acronym', 'a', 'img', 'br',
364 364
        'br', 'map', 'q', 'sub', 'sup', 'span', 'bdo'
365 365
    ]
......
375 375
        ['+', 'ins', :limit],
376 376
        ['^', 'sup', :limit],
377 377
        ['~', 'sub', :limit]
378
    ] 
378
    ]
379 379
    QTAGS_JOIN = QTAGS.map {|rc, ht, rtype| Regexp::quote rc}.join('|')
380
    
380

  
381 381
    QTAGS.collect! do |rc, ht, rtype|
382 382
        rcq = Regexp::quote rc
383 383
        re =
......
397 397
                (#{C})
398 398
                (?::(\S+))?
399 399
                ([[:word:]]|[^\s\-].*?[^\s\-])
400
                #{rcq}/xm 
400
                #{rcq}/xm
401 401
            end
402 402
        [rc, ht, re, rtype]
403 403
    end
......
466 466

  
467 467
    # Parses Textile attribute lists and builds an HTML attribute string
468 468
    def pba( text_in, element = "" )
469
        
469

  
470 470
        return +'' unless text_in
471 471

  
472 472
        style = []
......
487 487

  
488 488
        cls = $1 if
489 489
            text.sub!( /\(([^()]+?)\)/, '' )
490
                        
490

  
491 491
        style << "padding-left:#{ $1.length }em;" if
492 492
            text.sub!( /([(]+)/, '' )
493 493

  
......
512 512
        atts << " id=\"#{ id }\"" if id
513 513
        atts << " colspan=\"#{ colspan }\"" if colspan
514 514
        atts << " rowspan=\"#{ rowspan }\"" if rowspan
515
        
515

  
516 516
        atts
517 517
    end
518 518

  
......
527 527
    end
528 528

  
529 529
    TABLE_RE = /^(?:table(_?#{S}#{A}#{C})\. ?\n)?^(#{A}#{C}\.? ?\|.*?\|)(\n\n|\Z)/m
530
    
530

  
531 531
    # Parses a Textile table block, building HTML from the result.
532
    def block_textile_table( text ) 
532
    def block_textile_table( text )
533 533
        text.gsub!( TABLE_RE ) do |matches|
534 534

  
535 535
            tatts, fullrow = $~[1..2]
......
540 540
            fullrow.each_line do |row|
541 541
                ratts, row = pba( $1, 'tr' ), $2 if row =~ /^(#{A}#{C}\. )(.*)/m
542 542
                cells = []
543
                # the regexp prevents wiki links with a | from being cut as cells 
543
                # the regexp prevents wiki links with a | from being cut as cells
544 544
                row.scan(/\|(_?#{S}#{A}#{C}\. ?)?((\[\[[^|\]]*\|[^|\]]*\]\]|[^|])*?)(?=\|)/) do |modifiers, cell|
545 545
                    ctyp = 'd'
546 546
                    ctyp = 'h' if modifiers && modifiers =~ /^_/
......
549 549
                    catts = pba( modifiers, 'td' ) if modifiers
550 550

  
551 551
                    catts = shelve( catts ) if catts
552
                    cells << "\t\t\t<t#{ ctyp }#{ catts }>#{ cell }</t#{ ctyp }>" 
552
                    cells << "\t\t\t<t#{ ctyp }#{ catts }>#{ cell }</t#{ ctyp }>"
553 553
                end
554 554
                ratts = shelve( ratts ) if ratts
555 555
                rows << "\t\t<tr#{ ratts }>\n#{ cells.join( "\n" ) }\n\t\t</tr>"
......
562 562
    LISTS_CONTENT_RE = /^([#*]+)(#{A}#{C}) (.*)$/m
563 563

  
564 564
    # Parses Textile lists and generates HTML
565
    def block_textile_lists( text ) 
565
    def block_textile_lists( text )
566 566
        text.gsub!( LISTS_RE ) do |match|
567 567
            lines = match.split( /\n/ )
568 568
            last_line = -1
569 569
            depth = []
570 570
            lines.each_with_index do |line, line_id|
571
                if line =~ LISTS_CONTENT_RE 
571
                if line =~ LISTS_CONTENT_RE
572 572
                    tl,atts,content = $~[1..3]
573 573
                    if depth.last
574 574
                        if depth.last.length > tl.length
......
604 604
            lines.join( "\n" )
605 605
        end
606 606
    end
607
    
607

  
608 608
    QUOTES_RE = /(^>+([^\n]*?)(\n|$))+/m
609 609
    QUOTES_CONTENT_RE = /^([> ]+)(.*)$/m
610
    
610

  
611 611
    def block_textile_quotes( text )
612 612
      text.gsub!( QUOTES_RE ) do |match|
613 613
        lines = match.split( /\n/ )
614 614
        quotes = +''
615 615
        indent = 0
616 616
        lines.each do |line|
617
          line =~ QUOTES_CONTENT_RE 
617
          line =~ QUOTES_CONTENT_RE
618 618
          bq,content = $1, $2
619 619
          l = bq.count('>')
620 620
          if l != indent
......
635 635
        @
636 636
        (?=\W)/x
637 637

  
638
    def inline_textile_code( text ) 
638
    def inline_textile_code( text )
639 639
        text.gsub!( CODE_RE ) do |m|
640 640
            before,lang,code,after = $~[1..4]
641 641
            lang = " lang=\"#{ lang }\"" if lang
......
643 643
        end
644 644
    end
645 645

  
646
    def lT( text ) 
646
    def lT( text )
647 647
        text =~ /\#$/ ? 'o' : 'u'
648 648
    end
649 649

  
......
678 678
                        end
679 679
                    end
680 680

  
681
                    block_applied = 0 
681
                    block_applied = 0
682 682
                    @rules.each do |rule_name|
683 683
                        block_applied += 1 if ( rule_name.to_s.match /^block_/ and method( rule_name ).call( blk ) )
684 684
                    end
......
725 725

  
726 726
    BLOCK_RE = /^(([a-z]+)(\d*))(#{A}#{C})\.(?::(\S+))? (.*)$/m
727 727

  
728
    def block_textile_prefix( text ) 
728
    def block_textile_prefix( text )
729 729
        if text =~ BLOCK_RE
730 730
            tag,tagpre,num,atts,cite,content = $~[1..6]
731 731
            atts = pba( atts )
......
735 735
            if respond_to? "textile_#{ tag }", true
736 736
              replacement = method( "textile_#{ tag }" ).call( tag, atts, cite, content )
737 737
            elsif respond_to? "textile_#{ tagpre }_", true
738
              replacement = method( "textile_#{ tagpre }_" ).call( tagpre, num, atts, cite, content )  
738
              replacement = method( "textile_#{ tagpre }_" ).call( tagpre, num, atts, cite, content )
739 739
            end
740 740
            text.gsub!( $& ) { replacement } if replacement
741 741
        end
742 742
    end
743
    
743

  
744 744
    SETEXT_RE = /\A(.+?)\n([=-])[=-]* *$/m
745 745
    def block_markdown_setext( text )
746 746
        if text =~ SETEXT_RE
......
792 792
    def block_markdown_lists( text )
793 793
    end
794 794

  
795
    def inline_textile_span( text ) 
795
    def inline_textile_span( text )
796 796
        QTAGS.each do |qtag_rc, ht, qtag_re, rtype|
797 797
            text.gsub!( qtag_re ) do |m|
798
             
798

  
799 799
                case rtype
800 800
                when :limit
801 801
                    sta,oqs,qtag,content,oqa = $~[1..6]
......
828 828
            (                          # $url
829 829
            (\/|[a-zA-Z]+:\/\/|www\.|mailto:)  # $proto
830 830
            [[:alnum:]_\/]\S+?
831
            )               
831
            )
832 832
            (\/)?                      # $slash
833 833
            ([^[:alnum:]_\=\/;\(\)\-]*?)       # $post
834 834
            )
835 835
            (?=<|\s|$)
836
        /x 
836
        /x
837 837
#"
838
    def inline_textile_link( text ) 
838
    def inline_textile_link( text )
839 839
        text.gsub!( LINK_RE ) do |m|
840 840
          all,pre,atts,text,title,url,proto,slash,post = $~[1..9]
841 841
          if text.include?('<br />')
......
843 843
          else
844 844
            url, url_title = check_refs( url )
845 845
            title ||= url_title
846
            
846

  
847 847
            # Idea below : an URL with unbalanced parethesis and
848 848
            # ending by ')' is put into external parenthesis
849 849
            if ( url[-1]==?) and ((url.count("(") - url.count(")")) < 0 ) )
......
854 854
            atts = +" href=\"#{ htmlesc url }#{ slash }\"#{ atts }"
855 855
            atts << " title=\"#{ htmlesc title }\"" if title
856 856
            atts = shelve( atts ) if atts
857
            
857

  
858 858
            external = (url =~ /^https?:\/\//) ? ' class="external"' : ''
859
            
859

  
860 860
            "#{ pre }<a#{ atts }#{ external }>#{ text }</a>#{ post }"
861 861
          end
862 862
        end
......
867 867
            [ ]?                # opt. space
868 868
            (?:\n[ ]*)?         # one optional newline followed by spaces
869 869
            \[(.*?)\]           # $id
870
        /x 
870
        /x
871 871

  
872
    def inline_markdown_reflink( text ) 
872
    def inline_markdown_reflink( text )
873 873
        text.gsub!( MARKDOWN_REFLINK_RE ) do |m|
874 874
            text, id = $~[1..2]
875 875

  
......
878 878
            else
879 879
                url, title = check_refs( id )
880 880
            end
881
            
881

  
882 882
            atts = " href=\"#{ url }\""
883 883
            atts << " title=\"#{ title }\"" if title
884 884
            atts = shelve( atts )
885
            
885

  
886 886
            "<a#{ atts }>#{ text }</a>"
887 887
        end
888 888
    end
......
899 899
            \3                  # matching quote
900 900
            )?                  # title is optional
901 901
            \)
902
        /x 
902
        /x
903 903

  
904
    def inline_markdown_link( text ) 
904
    def inline_markdown_link( text )
905 905
        text.gsub!( MARKDOWN_LINK_RE ) do |m|
906 906
            text, url, quote, title = $~[1..4]
907 907

  
908 908
            atts = " href=\"#{ url }\""
909 909
            atts << " title=\"#{ title }\"" if title
910 910
            atts = shelve( atts )
911
            
911

  
912 912
            "<a#{ atts }>#{ text }</a>"
913 913
        end
914 914
    end
......
922 922
        end
923 923
    end
924 924

  
925
    def refs_textile( text ) 
925
    def refs_textile( text )
926 926
        text.gsub!( TEXTILE_REFS_RE ) do |m|
927 927
            flag, url = $~[2..3]
928 928
            @urlrefs[flag.downcase] = [url, nil]
929 929
            nil
930 930
        end
931 931
    end
932
    
932

  
933 933
    def refs_markdown( text )
934 934
        text.gsub!( MARKDOWN_REFS_RE ) do |m|
935 935
            flag, url = $~[2..3]
......
939 939
        end
940 940
    end
941 941

  
942
    def check_refs( text ) 
942
    def check_refs( text )
943 943
        ret = @urlrefs[text.downcase] if text
944 944
        ret || [text, nil]
945 945
    end
......
955 955
            (?:\(((?:[^\(\)]|\([^\)]+\))+?)\))?   # optional title
956 956
            \!                   # closing
957 957
            (?::#{ HYPERLINK })? # optional href
958
        /x 
958
        /x
959 959

  
960
    def inline_textile_image( text ) 
960
    def inline_textile_image( text )
961 961
        text.gsub!( IMAGE_RE )  do |m|
962 962
            stln,algn,atts,url,title,href,href_a1,href_a2 = $~[1..8]
963 963
            htmlesc title
964 964
            atts = pba( atts )
965 965
            atts = +" src=\"#{ htmlesc url.dup }\"#{ atts }"
966 966
            atts << " title=\"#{ title }\"" if title
967
            atts << " alt=\"#{ title }\"" 
967
            atts << " alt=\"#{ title }\""
968 968
            # size = @getimagesize($url);
969 969
            # if($size) $atts.= " $size[3]";
970 970

  
......
977 977
            out << "<a#{ shelve( " href=\"#{ href }\"" ) }>" if href
978 978
            out << "<img#{ shelve( atts ) } />"
979 979
            out << "</a>#{ href_a1 }#{ href_a2 }" if href
980
            
981
            if algn 
980

  
981
            if algn
982 982
                algn = h_align( algn )
983 983
                if stln == "<p>"
984 984
                    out = "<p style=\"float:#{ algn }\">#{ out }"
......
993 993
        end
994 994
    end
995 995

  
996
    def shelve( val ) 
996
    def shelve( val )
997 997
        @shelf << val
998 998
        " :redsh##{ @shelf.length }:"
999 999
    end
1000
    
1001
    def retrieve( text ) 
1000

  
1001
    def retrieve( text )
1002 1002
        text.gsub!(/ :redsh#(\d+):/) do
1003 1003
          @shelf[$1.to_i - 1] || $&
1004 1004
        end
1005 1005
    end
1006 1006

  
1007
    def incoming_entities( text ) 
1007
    def incoming_entities( text )
1008 1008
        ## turn any incoming ampersands into a dummy character for now.
1009 1009
        ## This uses a negative lookahead for alphanumerics followed by a semicolon,
1010 1010
        ## implying an incoming html entity, to be skipped
......
1012 1012
        text.gsub!( /&(?![#a-z0-9]+;)/i, "x%x%" )
1013 1013
    end
1014 1014

  
1015
    def no_textile( text ) 
1015
    def no_textile( text )
1016 1016
        text.gsub!( /(^|\s)==([^=]+.*?)==(\s|$)?/,
1017 1017
            '\1<notextile>\2</notextile>\3' )
1018 1018
        text.gsub!( /^ *==([^=]+.*?)==/m,
1019 1019
            '\1<notextile>\2</notextile>\3' )
1020 1020
    end
1021 1021

  
1022
    def clean_white_space( text ) 
1022
    def clean_white_space( text )
1023 1023
        # normalize line breaks
1024 1024
        text.gsub!( /\r\n/, "\n" )
1025 1025
        text.gsub!( /\r/, "\n" )
......
1045 1045
        end
1046 1046
    end
1047 1047

  
1048
    def footnote_ref( text ) 
1048
    def footnote_ref( text )
1049 1049
        text.gsub!( /\b\[([0-9]+?)\](\s)?/,
1050 1050
            '<sup><a href="#fn\1">\1</a></sup>\2' )
1051 1051
    end
1052
    
1052

  
1053 1053
    OFFTAGS = /(code|pre|kbd|notextile)/
1054 1054
    OFFTAG_MATCH = /(?:(<\/#{ OFFTAGS }\b>)|(<#{ OFFTAGS }\b[^>]*>))(.*?)(?=<\/?#{ OFFTAGS }\b\W|\Z)/mi
1055 1055
    OFFTAG_OPEN = /<#{ OFFTAGS }/
......
1071 1071
                    elsif line =~ OFFTAG_CLOSE
1072 1072
                        codepre -= 1
1073 1073
                        codepre = 0 if codepre < 0
1074
                    end 
1074
                    end
1075 1075
                elsif codepre.zero?
1076 1076
                    glyphs_textile( line, level + 1 )
1077 1077
                else
......
1118 1118
                    end
1119 1119
                    codepre -= 1 unless codepre.zero?
1120 1120
                    used_offtags = {} if codepre.zero?
1121
                end 
1121
                end
1122 1122
                line
1123 1123
            end
1124 1124
        end
......
1132 1132
        end
1133 1133
    end
1134 1134

  
1135
    def inline( text ) 
1135
    def inline( text )
1136 1136
        [/^inline_/, /^glyphs_/].each do |meth_re|
1137 1137
            @rules.each do |rule_name|
1138 1138
                method( rule_name ).call( text ) if rule_name.to_s.match( meth_re )
......
1140 1140
        end
1141 1141
    end
1142 1142

  
1143
    def h_align( text ) 
1143
    def h_align( text )
1144 1144
        H_ALGN_VALS[text]
1145 1145
    end
1146 1146

  
1147
    def v_align( text ) 
1147
    def v_align( text )
1148 1148
        V_ALGN_VALS[text]
1149 1149
    end
1150 1150

  
......
1158 1158
        'img' => ['src', 'alt', 'title'],
1159 1159
        'br' => [],
1160 1160
        'i' => nil,
1161
        'u' => nil, 
1161
        'u' => nil,
1162 1162
        'b' => nil,
1163 1163
        'pre' => nil,
1164 1164
        'kbd' => nil,
......
1183 1183
        'h3' => nil,
1184 1184
        'h4' => nil,
1185 1185
        'h5' => nil,
1186
        'h6' => nil, 
1186
        'h6' => nil,
1187 1187
        'blockquote' => ['cite']
1188 1188
    }
1189 1189

  
......
1211 1211
            end
1212 1212
        end
1213 1213
    end
1214
    
1215
    
1214

  
1215

  
1216 1216
    ALLOWED_TAGS = %w(redpre pre code kbd notextile)
1217 1217
    def escape_html_tags(text)
1218 1218
      text.gsub!(%r{<(\/?([!\w]+)[^<>\n]*)(>?)}) {|m| ALLOWED_TAGS.include?($2) ? "<#{$1}#{$3}" : "&lt;#{$1}#{'&gt;' unless $3.blank?}" }
1219 1219
    end
1220 1220
end
1221

  
test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb
281 281
This is a table with trailing whitespace in one row:
282 282

  
283 283
|cell11|cell12|
284
|cell21|cell22| 
284
|cell21|cell22|
285 285
|cell31|cell32|
286 286
RAW
287 287

  
......
383 383
    expected = '<p><img src="/images/comment.png&quot;onclick=&amp;#x61;&amp;#x6c;&amp;#x65;&amp;#x72;&amp;#x74;&amp;#x28;&amp;#x27;&amp;#x58;&amp;#x53;&amp;#x53;&amp;#x27;&amp;#x29;;&amp;#x22;" alt="" /></p>'
384 384
    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
385 385
  end
386
  
387
  
386

  
387

  
388 388
  STR_WITHOUT_PRE = [
389 389
  # 0
390 390
"h1. Title
......
414 414
Ut rhoncus elementum adipiscing."]
415 415

  
416 416
  TEXT_WITHOUT_PRE = STR_WITHOUT_PRE.join("\n\n").freeze
417
  
417

  
418 418
  def test_get_section_should_return_the_requested_section_and_its_hash
419 419
    assert_section_with_hash STR_WITHOUT_PRE[1], TEXT_WITHOUT_PRE, 2
420 420
    assert_section_with_hash STR_WITHOUT_PRE[2..3].join("\n\n"), TEXT_WITHOUT_PRE, 3
421 421
    assert_section_with_hash STR_WITHOUT_PRE[3], TEXT_WITHOUT_PRE, 5
422 422
    assert_section_with_hash STR_WITHOUT_PRE[4], TEXT_WITHOUT_PRE, 6
423
    
423

  
424 424
    assert_section_with_hash '', TEXT_WITHOUT_PRE, 0
425 425
    assert_section_with_hash '', TEXT_WITHOUT_PRE, 10
426 426
  end
427
  
427

  
428 428
  def test_update_section_should_update_the_requested_section
429 429
    replacement = "New text"
430
    
430

  
431 431
    assert_equal [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(2, replacement)
432 432
    assert_equal [STR_WITHOUT_PRE[0..1], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(3, replacement)
433 433
    assert_equal [STR_WITHOUT_PRE[0..2], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(5, replacement)
434 434
    assert_equal [STR_WITHOUT_PRE[0..3], replacement].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(6, replacement)
435
    
435

  
436 436
    assert_equal TEXT_WITHOUT_PRE, @formatter.new(TEXT_WITHOUT_PRE).update_section(0, replacement)
437 437
    assert_equal TEXT_WITHOUT_PRE, @formatter.new(TEXT_WITHOUT_PRE).update_section(10, replacement)
438 438
  end
439
  
439

  
440 440
  def test_update_section_with_hash_should_update_the_requested_section
441 441
    replacement = "New text"
442
    
442

  
443 443
    assert_equal [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"),
444 444
      @formatter.new(TEXT_WITHOUT_PRE).update_section(2, replacement, Digest::MD5.hexdigest(STR_WITHOUT_PRE[1]))
445 445
  end
446
  
446

  
447 447
  def test_update_section_with_wrong_hash_should_raise_an_error
448 448
    assert_raise Redmine::WikiFormatting::StaleSectionError do
449 449
      @formatter.new(TEXT_WITHOUT_PRE).update_section(2, "New text", Digest::MD5.hexdigest("Old text"))
......
494 494
  def test_update_section_should_not_escape_pre_content_outside_section
495 495
    text = STR_WITH_PRE.join("\n\n")
496 496
    replacement = "New text"
497
    
497

  
498 498
    assert_equal [STR_WITH_PRE[0..1], "New text"].flatten.join("\n\n"),
499 499
      @formatter.new(text).update_section(3, replacement)
500 500
  end
......
509 509
h1. Heading 2
510 510

  
511 511
Content 2
512
 
512

  
513 513
h1. Heading 3
514 514

  
515 515
Content 3
516 516

  
517 517
h1. Heading 4
518
 
518

  
519 519
Content 4
520 520
STR
521 521

  
......
633 633
  def to_html(text)
634 634
    @formatter.new(text).to_html
635 635
  end
636
  
636

  
637 637
  def assert_section_with_hash(expected, text, index)
638 638
    result = @formatter.new(text).get_section(index)
639
    
639

  
640 640
    assert_kind_of Array, result
641 641
    assert_equal 2, result.size
642 642
    assert_equal expected, result.first, "section content did not match"
643
-