asdasd

Groovy (beta) code posted by asdasd
created at 09 Mar 11:03, updated at 26 Aug 15:57

Edit | Back
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
require 'rack/utils'
require 'nokogiri'

module Rack
  class Codehighlighter
    include Rack::Utils

    # for logging use
    FORMAT = %{%s - [%s] [%s] "%s %s%s %s" (%s) %d %d %0.4f\n}
    
    def initialize(app, highlighter = :censor, opts = {})
      @app = app
      @highlighter = highlighter
      @opts = {
        :element => "pre",
        :pattern => /\A:::(\w+)\s*(\n|
)/i,  # 
 == line feed
        :reason => "[[--  ugly code removed  --]]", #8-)
        :markdown => false  
      }
      @opts.merge! opts
    end

    def call(env)
      began_at = Time.now
      status, headers, response = @app.call(env)
      headers = HeaderHash.new(headers)

      if !STATUS_WITH_NO_ENTITY_BODY.include?(status) &&
         !headers['transfer-encoding'] &&
          headers['content-type'] &&
          headers['content-type'].include?("text/html")

        content = ""
        response.each { |part| content += part }
        doc = Nokogiri::HTML(content)
        nodes = doc.search(@opts[:element])
        nodes.each do |node|
          s = node.inner_html || "[++where is the code?++]"
          if @opts[:markdown]
            node.parent.swap(send(@highlighter, s))  
          else
            node.swap(send(@highlighter, s))            
          end
        end

        body = doc.to_html
        headers['content-length'] = bytesize(body).to_s

        log(env, status, headers, began_at) if @opts[:logging]
        [status, headers, [body]]
      else
        [status, headers, response]  
      end
    end
    
    private

    def log(env, status, headers, began_at)
      # 127.0.0.1 - [ultraviolet] [10/Oct/2009 12:12:12] "GET /pastie HTTP/1.1" (text/html) 200 512 1.23
      now = Time.now
      logger = env['rack.errors']
      logger.write FORMAT % [
        env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-",
        @highlighter,
        now.strftime("%d/%b/%Y %H:%M:%S"),
        env["REQUEST_METHOD"],
        env["PATH_INFO"],
        env["QUERY_STRING"].empty? ? "" : "?"+env["QUERY_STRING"],
        env["HTTP_VERSION"],
        headers["content-type"] || "unknown",
        status.to_s[0..3],
        headers['content-length'],
        now - began_at
      ]
    end

    # simplifies testing
    def censor(string)
      "<pre class='censor'>#{@opts[:reason]}</pre>"
    end

    def syntax(string)
      # allow use html instead of xml
      translate = {
        'html' => 'xml',
        'c' => 'ansic',
        'css' => 'css21',
        'sql' => 'sqlite'
      }
      lang = 'unknown'
      refs = @opts[:pattern].match(string)  # extract language name
      if refs
        lang = refs[1]
        convertor = ::Syntax::Convertors::HTML.for_syntax translate[lang]
        convertor.convert(unescape_html(string.sub(@opts[:pattern], "")) || "[=this can'n happen=]")        
      else
        "<pre>#{string}</pre>"
      end
    end
    
    def <b style="color:black;background-color:#ffff66">coderay</b>(string)
      lang = 'unknown'
      refs = @opts[:pattern].match(string)  # extract language name
      if refs
        lang = refs[1]
        str = unescape_html(string.sub(@opts[:pattern], ""))
        "<pre class='<b style="color:black;background-color:#ffff66">CodeRay</b>'>#{::<b style="color:black;background-color:#ffff66">CodeRay</b>.encoder(:html).encode str, lang}</pre>"
      else
        "<pre class='<b style="color:black;background-color:#ffff66">CodeRay</b>'>#{string}</pre>"
      end
    end

    # experimental Javascript highlighter
    def prettify(string)
      # prettify uses short names; I want to use full names
      translate = {
        'ruby' => 'rb',
        'bash' => 'bsh',
        'javascript' => 'js',
        'python' => 'py'
      }
      lang = 'unknown'
      refs = @opts[:pattern].match(string)  # extract language name
      if refs 
        lang = refs[1]
        str = string.sub(@opts[:pattern], "")
        "<pre class='prettyprint lang-#{translate[lang] || lang}'>#{str}</pre>"
      else
        "<pre>#{string}</pre>"
      end
    end

    def pygments_api(string)
      require 'net/http'
      require 'uri'
      lang = 'unknown'
      refs = @opts[:pattern].match(string)  # extract language name
      if refs
        lang = refs[1]
        str = unescape_html(string.sub(@opts[:pattern], ""))
        req = Net::HTTP.post_form(URI.parse('http://pygments.appspot.com/'),
                            {'lang' => lang, 'code' => str})
        "#{req.body}"
      else
        "<pre>#{string}</pre>"
      end
    end

    def ultraviolet(string)
      opts = { :theme => 'dawn', :lines => false, :themes => {} }
      opts.merge! @opts
      lang = 'text'
      refs = @opts[:pattern].match(string)  # extract language name
      if refs
        lang = refs[1]
        theme = opts[:themes].collect do |k,v| 
          k if v.include? lang end.compact.first || opts[:theme]
        str = unescape_html(string.sub(@opts[:pattern], ""))
        "#{::Uv.parse(str, 'xhtml', lang, opts[:lines], theme)}"
      else
        "<pre class='#{opts[:theme]}'>#{string}</pre>"
      end
    end
    
    def unescape_html(string)
      string.to_s.gsub(/&#x000A;/i, "\n").gsub("&lt;", '<').gsub("&gt;", '>').gsub("&amp;", '&')
    end
    
  end
end
5.31 KB in 16 ms with coderay