Skip to content
Snippets Groups Projects
redcloth3.rb 36.9 KiB
Newer Older
            end unless text.empty?
            if indt.nonzero?
                text.gsub!( /^ {#{indt}}/, '' )
            end
        end
    end

    def footnote_ref( text ) 
        text.gsub!( /\b\[([0-9]+?)\](\s)?/,
            '<sup><a href="#fn\1">\1</a></sup>\2' )
    end
    
    OFFTAGS = /(code|pre|kbd|notextile)/
    OFFTAG_MATCH = /(?:(<\/#{ OFFTAGS }>)|(<#{ OFFTAGS }[^>]*>))(.*?)(?=<\/?#{ OFFTAGS }|\Z)/mi
    OFFTAG_OPEN = /<#{ OFFTAGS }/
    OFFTAG_CLOSE = /<\/?#{ OFFTAGS }/
    HASTAG_MATCH = /(<\/?\w[^\n]*?>)/m
    ALLTAG_MATCH = /(<\/?\w[^\n]*?>)|.*?(?=<\/?\w[^\n]*?>|$)/m

    def glyphs_textile( text, level = 0 )
        if text !~ HASTAG_MATCH
            footnote_ref text
        else
            codepre = 0
            text.gsub!( ALLTAG_MATCH ) do |line|
                ## matches are off if we're between <code>, <pre> etc.
                if $1
                    if line =~ OFFTAG_OPEN
                        codepre += 1
                    elsif line =~ OFFTAG_CLOSE
                        codepre -= 1
                        codepre = 0 if codepre < 0
                    end 
                elsif codepre.zero?
                    glyphs_textile( line, level + 1 )
                else
                    htmlesc( line, :NoQuotes )
                end
                # p [level, codepre, line]

                line
            end
        end
    end

    def rip_offtags( text )
        if text =~ /<.*>/
            ## strip and encode <pre> content
            codepre, used_offtags = 0, {}
            text.gsub!( OFFTAG_MATCH ) do |line|
                if $3
                    offtag, aftertag = $4, $5
                    codepre += 1
                    used_offtags[offtag] = true
                    if codepre - used_offtags.length > 0
Jean-Philippe Lang's avatar
Jean-Philippe Lang committed
                        htmlesc( line, :NoQuotes )
Jean-Philippe Lang's avatar
Jean-Philippe Lang committed
                        htmlesc( aftertag, :NoQuotes ) if aftertag
                        line = "<redpre##{ @pre_list.length }>"
                        $3.match(/<#{ OFFTAGS }([^>]*)>/)
                        tag = $1
                        $2.to_s.match(/(class\=\S+)/i)
                        tag << " #{$1}" if $1
                        @pre_list << "<#{ tag }>#{ aftertag }"
                    end
                elsif $1 and codepre > 0
                    if codepre - used_offtags.length > 0
Jean-Philippe Lang's avatar
Jean-Philippe Lang committed
                        htmlesc( line, :NoQuotes )
                        @pre_list.last << line
                        line = ""
                    end
                    codepre -= 1 unless codepre.zero?
                    used_offtags = {} if codepre.zero?
                end 
                line
            end
        end
        text
    end

    def smooth_offtags( text )
        unless @pre_list.empty?
            ## replace <pre> content
            text.gsub!( /<redpre#(\d+)>/ ) { @pre_list[$1.to_i] }
        end
    end

    def inline( text ) 
        [/^inline_/, /^glyphs_/].each do |meth_re|
            @rules.each do |rule_name|
                method( rule_name ).call( text ) if rule_name.to_s.match( meth_re )
            end
        end
    end

    def h_align( text ) 
        H_ALGN_VALS[text]
    end

    def v_align( text ) 
        V_ALGN_VALS[text]
    end

    def textile_popup_help( name, windowW, windowH )
        ' <a target="_blank" href="http://hobix.com/textile/#' + helpvar + '" onclick="window.open(this.href, \'popupwindow\', \'width=' + windowW + ',height=' + windowH + ',scrollbars,resizable\'); return false;">' + name + '</a><br />'
    end

    # HTML cleansing stuff
    BASIC_TAGS = {
        'a' => ['href', 'title'],
        'img' => ['src', 'alt', 'title'],
        'br' => [],
        'i' => nil,
        'u' => nil, 
        'b' => nil,
        'pre' => nil,
        'kbd' => nil,
        'code' => ['lang'],
        'cite' => nil,
        'strong' => nil,
        'em' => nil,
        'ins' => nil,
        'sup' => nil,
        'sub' => nil,
        'del' => nil,
        'table' => nil,
        'tr' => nil,
        'td' => ['colspan', 'rowspan'],
        'th' => nil,
        'ol' => nil,
        'ul' => nil,
        'li' => nil,
        'p' => nil,
        'h1' => nil,
        'h2' => nil,
        'h3' => nil,
        'h4' => nil,
        'h5' => nil,
        'h6' => nil, 
        'blockquote' => ['cite']
    }

    def clean_html( text, tags = BASIC_TAGS )
        text.gsub!( /<!\[CDATA\[/, '' )
        text.gsub!( /<(\/*)(\w+)([^>]*)>/ ) do
            raw = $~
            tag = raw[2].downcase
            if tags.has_key? tag
                pcs = [tag]
                tags[tag].each do |prop|
                    ['"', "'", ''].each do |q|
                        q2 = ( q != '' ? q : '\s' )
                        if raw[3] =~ /#{prop}\s*=\s*#{q}([^#{q2}]+)#{q}/i
                            attrv = $1
                            next if prop == 'src' and attrv =~ %r{^(?!http)\w+:}
                            pcs << "#{prop}=\"#{$1.gsub('"', '\\"')}\""
                            break
                        end
                    end
                end if tags[tag]
                "<#{raw[1]}#{pcs.join " "}>"
            else
                " "
            end
        end
    end
    ALLOWED_TAGS = %w(redpre pre code notextile)
Jean-Philippe Lang's avatar
Jean-Philippe Lang committed
    
    def escape_html_tags(text)
      text.gsub!(%r{<(\/?([!\w]+)[^<>\n]*)(>?)}) {|m| ALLOWED_TAGS.include?($2) ? "<#{$1}#{$3}" : "&lt;#{$1}#{'&gt;' unless $3.blank?}" }
Jean-Philippe Lang's avatar
Jean-Philippe Lang committed
    end