rack-coderay 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,81 @@
1
+ = CodeRay Syntax Highlighter for Rack
2
+
3
+ Rack::Coderay parses text/html markup and replaces code with output
4
+ from the CodeRay gem (http://coderay.rubychan.de/), producing syntax highlighting.
5
+ By default, this component looks for <pre lang="xxxx">...</pre>
6
+ blocks, where 'xxxx' is any of the languages supported by CodeRay (e.g. 'ruby').
7
+ See http://coderay.rubychan.de/doc/classes/CodeRay/Scanners.html
8
+
9
+ For more information about the Rack specification, check out http://rack.rubyforge.org
10
+
11
+ == Installation
12
+
13
+ Prerequisites:
14
+
15
+ -Rack gem (sudo gem install rack)
16
+ -CodeRay gem (sudo gem install coderay)
17
+
18
+ From Gem:
19
+
20
+ $ sudo gem install webficient-rack-coderay
21
+
22
+ With a local working copy:
23
+
24
+ $ git clone git://github.com/webficient/rack-coderay.git
25
+ $ rake build && sudo rake install
26
+
27
+ == Usage
28
+
29
+ Basic Usage
30
+ -----------
31
+
32
+ Rack::Coderay is implemented as a piece of Rack middleware and can be used with
33
+ any Rack-based application. If your application includes a rackup (`.ru`) file
34
+ or uses Rack::Builder to construct the application pipeline, simply require
35
+ and use as follows:
36
+
37
+ require 'rack/coderay'
38
+
39
+ use Rack::Coderay
40
+ run app
41
+
42
+ Using with Rails
43
+ ----------------
44
+
45
+ Add this to your `config/environment.rb`:
46
+
47
+ # above Rails::Initializer block
48
+ require 'rack/coderay'
49
+
50
+ # inside Rails::Initializer block
51
+ config.middleware.use Rack::Coderay
52
+
53
+ You should now see `Rack::Coderay` listed in the middleware pipeline:
54
+
55
+ rake middleware
56
+
57
+ Configuration Options
58
+ ---------------------
59
+
60
+ To override the default markup trigger (<pre lang="xxxx">), you
61
+ can pass in a css or xpath selector as the second argument:
62
+
63
+ # Rails example
64
+ config.middleware.use Rack::Coderay, "//div[@lang]"
65
+
66
+ To set additional CodeRay gem options, pass a hash as the third argument:
67
+
68
+ # Rails example
69
+ config.middleware.use Rack::Coderay,
70
+ "//pre[@lang]",
71
+ :line_numbers => :table
72
+
73
+ Stylesheet
74
+ ----------
75
+ You can grab the latest CSS from the CodeRay site at http://coderay.rubychan.de/stylesheets/coderay.css.
76
+
77
+ A copy has been embedded in the Rack::Coderay gem under the /resources directory for your convenience.
78
+
79
+ == Copyright
80
+
81
+ Copyright (c) 2009 Phil Misiowiec, Webficient LLC. See MIT-LICENSE for details.
@@ -0,0 +1,46 @@
1
+ require 'rack'
2
+
3
+ # = CodeRay Syntax Highlighter Rack Appliance
4
+ #
5
+ # Rack::Coderay parses text/html markup and replaces code with output
6
+ # from the CodeRay gem (http://coderay.rubychan.de/), producing syntax highlighting.
7
+ # By default, this component looks for <pre lang="xxxx">...</pre>
8
+ # blocks, where 'xxxx' is any of the languages supported by CodeRay (e.g. 'ruby').
9
+ # See http://coderay.rubychan.de/doc/classes/CodeRay/Scanners.html
10
+ #
11
+ # You can re-configure Rack::Coderay to look for a different trigger
12
+ # but it needs to have a 'lang' attribute.
13
+ #
14
+ # === Usage
15
+ #
16
+ # Within a rackup file (or with Rack::Builder):
17
+ # require 'rack/coderay'
18
+ # use Rack::Coderay
19
+ # run app
20
+ #
21
+ # Rails example:
22
+ # # above Rails::Initializer block
23
+ # require 'rack/coderay'
24
+ #
25
+ # # inside Rails::Initializer block
26
+ # config.middleware.use Rack::Coderay
27
+ #
28
+ # To override the default markup trigger (<pre lang="xxxx">), you
29
+ # can pass in a css or xpath selector as the second argument:
30
+ #
31
+ # config.middleware.use Rack::Coderay, "//div[@lang]"
32
+ #
33
+ # To set additional CodeRay gem options, pass a hash as the third argument:
34
+ #
35
+ # config.middleware.use Rack::Coderay,
36
+ # "//pre[@lang]",
37
+ # :line_numbers => :table
38
+ module Rack::Coderay
39
+ autoload :Parser, 'rack/coderay/parser'
40
+
41
+ # Create a new Rack::Coderay middleware component that automatically
42
+ # highlights syntax using the CodeRay gem.
43
+ def self.new(backend, markup_trigger = "//pre[@lang]", options = {})
44
+ Parser.new(backend, markup_trigger, options)
45
+ end
46
+ end
@@ -0,0 +1,61 @@
1
+ require 'coderay'
2
+ require 'hpricot'
3
+
4
+ module Rack::Coderay
5
+ # This class is the interface between Rack and the CodeRay gem
6
+ class Parser
7
+
8
+ # Defaults for the Coderay gem config
9
+ DEFAULT_CODERAY_OPTS = {
10
+ :css => :class
11
+ }
12
+
13
+ # Coderay gem options for HTML encoder,
14
+ # see http://coderay.rubychan.de/doc/classes/CodeRay/Encoders/HTML.html
15
+ attr_accessor :coderay_options
16
+
17
+ def initialize(app, markup_trigger, options = {})
18
+ @app = app
19
+ @markup_trigger = markup_trigger
20
+ self.coderay_options = DEFAULT_CODERAY_OPTS.merge(options)
21
+ raise "Markup trigger must include a 'lang' attribute" if !markup_trigger.include?('lang')
22
+ end
23
+
24
+ # method required by Rack interface
25
+ def call(env)
26
+ call! env
27
+ end
28
+
29
+ # thread safe version using shallow copy of env
30
+ def call!(env)
31
+ @env = env.dup
32
+ status, headers, response = @app.call(@env)
33
+ if headers["Content-Type"] && headers["Content-Type"].include?("text/html")
34
+ headers.delete('Content-Length')
35
+ response = Rack::Response.new(
36
+ response = parse_and_replace(response.respond_to?(:body) ? response.body : response),
37
+ status,
38
+ headers
39
+ )
40
+ response.finish
41
+ response.to_a
42
+ else
43
+ [status, headers, response]
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def parse_and_replace(content) #:nodoc:
50
+ doc = Hpricot(content.is_a?(Array) ? content[0] : content)
51
+ doc.search(@markup_trigger).each do |node|
52
+ node.swap(coderay_render(node.inner_html, node['lang']))
53
+ end
54
+ doc.to_original_html
55
+ end
56
+
57
+ def coderay_render(text, language) #:nodoc:
58
+ ::CodeRay.scan(text, language.to_sym).div(self.coderay_options)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,130 @@
1
+ .CodeRay {
2
+ background-color: #f8f8f8;
3
+ border: 1px solid silver;
4
+ font-family: 'Courier New', 'Terminal', monospace;
5
+ color: #000;
6
+ }
7
+ .CodeRay pre { margin: 0px }
8
+
9
+ div.CodeRay { }
10
+
11
+ span.CodeRay { white-space: pre; border: 0px; padding: 2px }
12
+
13
+ table.CodeRay { border-collapse: collapse; width: 100%; padding: 2px }
14
+ table.CodeRay td { padding: 2px 4px; vertical-align: top }
15
+
16
+ .CodeRay .line_numbers, .CodeRay .no {
17
+ background-color: #def;
18
+ color: gray;
19
+ text-align: right;
20
+ }
21
+ .CodeRay .line_numbers tt { font-weight: bold }
22
+ .CodeRay .line_numbers .highlighted { color: red }
23
+ .CodeRay .no { padding: 0px 4px }
24
+ .CodeRay .code { width: 100% }
25
+
26
+ ol.CodeRay { font-size: 10pt }
27
+ ol.CodeRay li { white-space: pre }
28
+
29
+ .CodeRay .code pre { overflow: auto }
30
+
31
+ .CodeRay .debug { color:white ! important; background:blue ! important; }
32
+
33
+ .CodeRay .af { color:#00C }
34
+ .CodeRay .an { color:#007 }
35
+ .CodeRay .at { color:#f08 }
36
+ .CodeRay .av { color:#700 }
37
+ .CodeRay .aw { color:#C00 }
38
+ .CodeRay .bi { color:#509; font-weight:bold }
39
+ .CodeRay .c { color:#888; }
40
+
41
+ .CodeRay .ch { color:#04D }
42
+ .CodeRay .ch .k { color:#04D }
43
+ .CodeRay .ch .dl { color:#039 }
44
+
45
+ .CodeRay .cl { color:#B06; font-weight:bold }
46
+ .CodeRay .cm { color:#A08; font-weight:bold }
47
+ .CodeRay .co { color:#036; font-weight:bold }
48
+ .CodeRay .cr { color:#0A0 }
49
+ .CodeRay .cv { color:#369 }
50
+ .CodeRay .de { color:#B0B; }
51
+ .CodeRay .df { color:#099; font-weight:bold }
52
+ .CodeRay .di { color:#088; font-weight:bold }
53
+ .CodeRay .dl { color:black }
54
+ .CodeRay .do { color:#970 }
55
+ .CodeRay .dt { color:#34b }
56
+ .CodeRay .ds { color:#D42; font-weight:bold }
57
+ .CodeRay .e { color:#666; font-weight:bold }
58
+ .CodeRay .en { color:#800; font-weight:bold }
59
+ .CodeRay .er { color:#F00; background-color:#FAA }
60
+ .CodeRay .ex { color:#F00; font-weight:bold }
61
+ .CodeRay .fl { color:#60E; font-weight:bold }
62
+ .CodeRay .fu { color:#06B; font-weight:bold }
63
+ .CodeRay .gv { color:#d70; font-weight:bold }
64
+ .CodeRay .hx { color:#058; font-weight:bold }
65
+ .CodeRay .i { color:#00D; font-weight:bold }
66
+ .CodeRay .ic { color:#B44; font-weight:bold }
67
+
68
+ .CodeRay .il { background: #ddd; color: black }
69
+ .CodeRay .il .il { background: #ccc }
70
+ .CodeRay .il .il .il { background: #bbb }
71
+ .CodeRay .il .idl { background: #ddd; font-weight: bold; color: #666 }
72
+ .CodeRay .idl { background-color: #bbb; font-weight: bold; color: #666; }
73
+
74
+ .CodeRay .im { color:#f00; }
75
+ .CodeRay .in { color:#B2B; font-weight:bold }
76
+ .CodeRay .iv { color:#33B }
77
+ .CodeRay .la { color:#970; font-weight:bold }
78
+ .CodeRay .lv { color:#963 }
79
+ .CodeRay .oc { color:#40E; font-weight:bold }
80
+ .CodeRay .of { color:#000; font-weight:bold }
81
+ .CodeRay .op { }
82
+ .CodeRay .pc { color:#038; font-weight:bold }
83
+ .CodeRay .pd { color:#369; font-weight:bold }
84
+ .CodeRay .pp { color:#579; }
85
+ .CodeRay .ps { color:#00C; font-weight: bold; }
86
+ .CodeRay .pt { color:#349; font-weight:bold }
87
+ .CodeRay .r, .kw { color:#080; font-weight:bold }
88
+
89
+ .CodeRay .ke { color: #808; }
90
+ .CodeRay .ke .dl { color: #606; }
91
+ .CodeRay .ke .ch { color: #80f; }
92
+ .CodeRay .vl { color: #088; }
93
+
94
+ .CodeRay .rx { background-color:#fff0ff }
95
+ .CodeRay .rx .k { color:#808 }
96
+ .CodeRay .rx .dl { color:#404 }
97
+ .CodeRay .rx .mod { color:#C2C }
98
+ .CodeRay .rx .fu { color:#404; font-weight: bold }
99
+
100
+ .CodeRay .s { background-color:#fff0f0; color: #D20; }
101
+ .CodeRay .s .s { background-color:#ffe0e0 }
102
+ .CodeRay .s .s .s { background-color:#ffd0d0 }
103
+ .CodeRay .s .k { }
104
+ .CodeRay .s .ch { color: #b0b; }
105
+ .CodeRay .s .dl { color: #710; }
106
+
107
+ .CodeRay .sh { background-color:#f0fff0; color:#2B2 }
108
+ .CodeRay .sh .k { }
109
+ .CodeRay .sh .dl { color:#161 }
110
+
111
+ .CodeRay .sy { color:#A60 }
112
+ .CodeRay .sy .k { color:#A60 }
113
+ .CodeRay .sy .dl { color:#630 }
114
+
115
+ .CodeRay .ta { color:#070 }
116
+ .CodeRay .tf { color:#070; font-weight:bold }
117
+ .CodeRay .ts { color:#D70; font-weight:bold }
118
+ .CodeRay .ty { color:#339; font-weight:bold }
119
+ .CodeRay .v { color:#036 }
120
+ .CodeRay .xt { color:#444 }
121
+
122
+ .CodeRay .ins { background: #afa; }
123
+ .CodeRay .del { background: #faa; }
124
+ .CodeRay .chg { color: #aaf; background: #007; }
125
+ .CodeRay .head { color: #f8f; background: #505 }
126
+
127
+ .CodeRay .ins .ins { color: #080; font-weight:bold }
128
+ .CodeRay .del .del { color: #800; font-weight:bold }
129
+ .CodeRay .chg .chg { color: #66f; }
130
+ .CodeRay .head .head { color: #f4f; }
@@ -0,0 +1,106 @@
1
+ require 'test_helper'
2
+
3
+ class RackCoderayTest < Test::Unit::TestCase
4
+
5
+ def get_response(path, body, markup_trigger = "//pre[@lang]", options = {})
6
+ app = Rack::Builder.new do
7
+ use Rack::Coderay, markup_trigger, options
8
+ run lambda { |env| [200, {'Content-Type' => 'text/html'}, [body] ] }
9
+ end
10
+ Rack::MockRequest.new(app).get(path)
11
+ end
12
+
13
+ context "Rack::Coderay" do
14
+ context "with default options" do
15
+ setup do
16
+ @response = get_response('/', %Q{
17
+ <pre lang="ruby">
18
+ class Foo
19
+ def bar
20
+ end
21
+ end
22
+ </pre>})
23
+ end
24
+ should "replace markup with CodeRay formatting" do
25
+ assert @response.body.include?(%Q{<div class="CodeRay">})
26
+ end
27
+ end
28
+
29
+ context "with markup trigger set to a non-matching tag" do
30
+ setup do
31
+ @response = get_response('/', %Q{
32
+ <pre lang="ruby">
33
+ class Foo
34
+ def bar
35
+ end
36
+ end
37
+ </pre>}, '//div[@lang]')
38
+ end
39
+ should "not replace markup with CodeRay formatting" do
40
+ assert @response.body.include?(%Q{<pre lang="ruby">})
41
+ end
42
+ end
43
+
44
+ context "with markup trigger set to //div[@lang]" do
45
+ setup do
46
+ @response = get_response('/', %Q{
47
+ <div lang="ruby">
48
+ class Foo
49
+ def bar
50
+ end
51
+ end
52
+ </div>}, '//div[@lang]')
53
+ end
54
+ should "replace markup with CodeRay formatting" do
55
+ assert @response.body.include?(%Q{<div class="CodeRay">})
56
+ end
57
+ end
58
+
59
+ context "with :css property set to :style" do
60
+ setup do
61
+ @response = get_response('/', %Q{
62
+ <pre lang="ruby">
63
+ class Foo
64
+ def bar
65
+ end
66
+ end
67
+ </pre>}, "//pre[@lang]", :css => :style)
68
+ end
69
+ should "replace markup with CodeRay formatting and use embedded styles" do
70
+ assert @response.body.include?(%Q{<span style="color:#080;font-weight:bold">})
71
+ end
72
+ end
73
+
74
+ context "with different order of attributes in markup trigger" do
75
+ setup do
76
+ @response = get_response('/', %Q{
77
+ <pre class="blah" lang="json">
78
+ { "just": "an", "example": 42 }
79
+ </pre>})
80
+ end
81
+ should "replace markup with CodeRay formatting" do
82
+ assert @response.body.include?(%Q{<div class="CodeRay">})
83
+ end
84
+ end
85
+
86
+ context "with lang set to json" do
87
+ setup do
88
+ @response = get_response('/', %Q{
89
+ <pre lang="json">
90
+ { "just": "an", "example": 42 }
91
+ </pre>})
92
+ end
93
+ should "replace markup with CodeRay formatting" do
94
+ assert @response.body.include?(%Q{<div class="CodeRay">})
95
+ end
96
+ end
97
+
98
+ context "when markup trigger is missing 'lang' attribute" do
99
+ should "raise a RuntimeError exception " do
100
+ assert_raise(RuntimeError) {
101
+ @response = get_response('/', 'blah', '//pre')
102
+ }
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,10 @@
1
+ $:.push File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require 'rubygems'
4
+ require 'test/unit'
5
+ require 'shoulda'
6
+ require 'rack/coderay'
7
+ require 'rack/mock'
8
+
9
+ class Test::Unit::TestCase
10
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-coderay
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Phil Misiowiec
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-28 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: coderay
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: hpricot
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: This Rack middleware component uses the CodeRay gem to automatically format code syntax by detecting a specific container in the final rendered markup.
36
+ email: phil@webficient.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.rdoc
43
+ files:
44
+ - lib/rack/coderay.rb
45
+ - lib/rack/coderay/parser.rb
46
+ - resources/coderay.css
47
+ - README.rdoc
48
+ has_rdoc: true
49
+ homepage: http://github.com/webficient/rack-coderay
50
+ licenses: []
51
+
52
+ post_install_message:
53
+ rdoc_options:
54
+ - --charset=UTF-8
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ requirements: []
70
+
71
+ rubyforge_project:
72
+ rubygems_version: 1.3.5
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Rack middleware that automatically formats code syntax using CodeRay gem
76
+ test_files:
77
+ - test/rack_coderay_test.rb
78
+ - test/test_helper.rb