raldred-coderay 0.9.0 → 0.9.339
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/README +128 -0
- data/lib/coderay.rb +319 -0
- data/lib/coderay/duo.rb +85 -0
- data/lib/coderay/encoder.rb +187 -0
- data/lib/coderay/encoders/_map.rb +9 -0
- data/lib/coderay/encoders/count.rb +21 -0
- data/lib/coderay/encoders/debug.rb +49 -0
- data/lib/coderay/encoders/div.rb +20 -0
- data/lib/coderay/encoders/html.rb +306 -0
- data/lib/coderay/encoders/html/css.rb +70 -0
- data/lib/coderay/encoders/html/numerization.rb +133 -0
- data/lib/coderay/encoders/html/output.rb +206 -0
- data/lib/coderay/encoders/json.rb +19 -0
- data/lib/coderay/encoders/null.rb +26 -0
- data/lib/coderay/encoders/page.rb +21 -0
- data/lib/coderay/encoders/span.rb +20 -0
- data/lib/coderay/encoders/statistic.rb +77 -0
- data/lib/coderay/encoders/term.rb +114 -0
- data/lib/coderay/encoders/text.rb +32 -0
- data/lib/coderay/encoders/tokens.rb +44 -0
- data/lib/coderay/encoders/xml.rb +71 -0
- data/lib/coderay/encoders/yaml.rb +22 -0
- data/lib/coderay/for_redcloth.rb +73 -0
- data/lib/coderay/helpers/file_type.rb +226 -0
- data/lib/coderay/helpers/gzip_simple.rb +123 -0
- data/lib/coderay/helpers/plugin.rb +339 -0
- data/lib/coderay/helpers/word_list.rb +124 -0
- data/lib/coderay/scanner.rb +271 -0
- data/lib/coderay/scanners/_map.rb +21 -0
- data/lib/coderay/scanners/c.rb +166 -0
- data/lib/coderay/scanners/css.rb +202 -0
- data/lib/coderay/scanners/debug.rb +61 -0
- data/lib/coderay/scanners/delphi.rb +150 -0
- data/lib/coderay/scanners/diff.rb +104 -0
- data/lib/coderay/scanners/groovy.rb +271 -0
- data/lib/coderay/scanners/html.rb +175 -0
- data/lib/coderay/scanners/java.rb +173 -0
- data/lib/coderay/scanners/java/builtin_types.rb +419 -0
- data/lib/coderay/scanners/java_script.rb +195 -0
- data/lib/coderay/scanners/json.rb +107 -0
- data/lib/coderay/scanners/nitro_xhtml.rb +132 -0
- data/lib/coderay/scanners/php.rb +404 -0
- data/lib/coderay/scanners/plaintext.rb +18 -0
- data/lib/coderay/scanners/python.rb +232 -0
- data/lib/coderay/scanners/rhtml.rb +71 -0
- data/lib/coderay/scanners/ruby.rb +386 -0
- data/lib/coderay/scanners/ruby/patterns.rb +232 -0
- data/lib/coderay/scanners/scheme.rb +142 -0
- data/lib/coderay/scanners/sql.rb +162 -0
- data/lib/coderay/scanners/xml.rb +17 -0
- data/lib/coderay/scanners/yaml.rb +142 -0
- data/lib/coderay/style.rb +20 -0
- data/lib/coderay/styles/_map.rb +7 -0
- data/lib/coderay/styles/cycnus.rb +151 -0
- data/lib/coderay/styles/murphy.rb +132 -0
- data/lib/coderay/token_classes.rb +86 -0
- data/lib/coderay/tokens.rb +387 -0
- metadata +59 -1
@@ -0,0 +1,70 @@
|
|
1
|
+
module CodeRay
|
2
|
+
module Encoders
|
3
|
+
|
4
|
+
class HTML
|
5
|
+
class CSS
|
6
|
+
|
7
|
+
attr :stylesheet
|
8
|
+
|
9
|
+
def CSS.load_stylesheet style = nil
|
10
|
+
CodeRay::Styles[style]
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize style = :default
|
14
|
+
@classes = Hash.new
|
15
|
+
style = CSS.load_stylesheet style
|
16
|
+
@stylesheet = [
|
17
|
+
style::CSS_MAIN_STYLES,
|
18
|
+
style::TOKEN_COLORS.gsub(/^(?!$)/, '.CodeRay ')
|
19
|
+
].join("\n")
|
20
|
+
parse style::TOKEN_COLORS
|
21
|
+
end
|
22
|
+
|
23
|
+
def [] *styles
|
24
|
+
cl = @classes[styles.first]
|
25
|
+
return '' unless cl
|
26
|
+
style = ''
|
27
|
+
1.upto(styles.size) do |offset|
|
28
|
+
break if style = cl[styles[offset .. -1]]
|
29
|
+
end
|
30
|
+
$stderr.puts 'Style not found: %p' % [styles] if $DEBUG and style.empty?
|
31
|
+
return style
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
CSS_CLASS_PATTERN = /
|
37
|
+
( # $1 = selectors
|
38
|
+
(?:
|
39
|
+
(?: \s* \. [-\w]+ )+
|
40
|
+
\s* ,?
|
41
|
+
)+
|
42
|
+
)
|
43
|
+
\s* \{ \s*
|
44
|
+
( [^\}]+ )? # $2 = style
|
45
|
+
\s* \} \s*
|
46
|
+
|
|
47
|
+
( . ) # $3 = error
|
48
|
+
/mx
|
49
|
+
def parse stylesheet
|
50
|
+
stylesheet.scan CSS_CLASS_PATTERN do |selectors, style, error|
|
51
|
+
raise "CSS parse error: '#{error.inspect}' not recognized" if error
|
52
|
+
for selector in selectors.split(',')
|
53
|
+
classes = selector.scan(/[-\w]+/)
|
54
|
+
cl = classes.pop
|
55
|
+
@classes[cl] ||= Hash.new
|
56
|
+
@classes[cl][classes] = style.to_s.strip.delete(' ').chomp(';')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
if $0 == __FILE__
|
68
|
+
require 'pp'
|
69
|
+
pp CodeRay::Encoders::HTML::CSS.new
|
70
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module CodeRay
|
2
|
+
module Encoders
|
3
|
+
|
4
|
+
class HTML
|
5
|
+
|
6
|
+
module Output
|
7
|
+
|
8
|
+
def numerize *args
|
9
|
+
clone.numerize!(*args)
|
10
|
+
end
|
11
|
+
|
12
|
+
=begin NUMERIZABLE_WRAPPINGS = {
|
13
|
+
:table => [:div, :page, nil],
|
14
|
+
:inline => :all,
|
15
|
+
:list => [:div, :page, nil]
|
16
|
+
}
|
17
|
+
NUMERIZABLE_WRAPPINGS.default = :all
|
18
|
+
=end
|
19
|
+
def numerize! mode = :table, options = {}
|
20
|
+
return self unless mode
|
21
|
+
|
22
|
+
options = DEFAULT_OPTIONS.merge options
|
23
|
+
|
24
|
+
start = options[:line_number_start]
|
25
|
+
unless start.is_a? Integer
|
26
|
+
raise ArgumentError, "Invalid value %p for :line_number_start; Integer expected." % start
|
27
|
+
end
|
28
|
+
|
29
|
+
#allowed_wrappings = NUMERIZABLE_WRAPPINGS[mode]
|
30
|
+
#unless allowed_wrappings == :all or allowed_wrappings.include? options[:wrap]
|
31
|
+
# raise ArgumentError, "Can't numerize, :wrap must be in %p, but is %p" % [NUMERIZABLE_WRAPPINGS, options[:wrap]]
|
32
|
+
#end
|
33
|
+
|
34
|
+
bold_every = options[:bold_every]
|
35
|
+
highlight_lines = options[:highlight_lines]
|
36
|
+
bolding =
|
37
|
+
if bold_every == false && highlight_lines == nil
|
38
|
+
proc { |line| line.to_s }
|
39
|
+
elsif highlight_lines.is_a? Enumerable
|
40
|
+
highlight_lines = highlight_lines.to_set
|
41
|
+
proc do |line|
|
42
|
+
if highlight_lines.include? line
|
43
|
+
"<strong class=\"highlighted\">#{line}</strong>" # highlighted line numbers in bold
|
44
|
+
else
|
45
|
+
line.to_s
|
46
|
+
end
|
47
|
+
end
|
48
|
+
elsif bold_every.is_a? Integer
|
49
|
+
raise ArgumentError, ":bolding can't be 0." if bold_every == 0
|
50
|
+
proc do |line|
|
51
|
+
if line % bold_every == 0
|
52
|
+
"<strong>#{line}</strong>" # every bold_every-th number in bold
|
53
|
+
else
|
54
|
+
line.to_s
|
55
|
+
end
|
56
|
+
end
|
57
|
+
else
|
58
|
+
raise ArgumentError, 'Invalid value %p for :bolding; false or Integer expected.' % bold_every
|
59
|
+
end
|
60
|
+
|
61
|
+
case mode
|
62
|
+
when :inline
|
63
|
+
max_width = (start + line_count).to_s.size
|
64
|
+
line_number = start
|
65
|
+
gsub!(/^/) do
|
66
|
+
line_number_text = bolding.call line_number
|
67
|
+
indent = ' ' * (max_width - line_number.to_s.size) # TODO: Optimize (10^x)
|
68
|
+
res = "<span class=\"no\">#{indent}#{line_number_text}</span> "
|
69
|
+
line_number += 1
|
70
|
+
res
|
71
|
+
end
|
72
|
+
|
73
|
+
when :table
|
74
|
+
# This is really ugly.
|
75
|
+
# Because even monospace fonts seem to have different heights when bold,
|
76
|
+
# I make the newline bold, both in the code and the line numbers.
|
77
|
+
# FIXME Still not working perfect for Mr. Internet Exploder
|
78
|
+
line_numbers = (start ... start + line_count).to_a.map(&bolding).join("\n")
|
79
|
+
line_numbers << "\n" # also for Mr. MS Internet Exploder :-/
|
80
|
+
line_numbers.gsub!(/\n/) { "<tt>\n</tt>" }
|
81
|
+
|
82
|
+
line_numbers_table_tpl = TABLE.apply('LINE_NUMBERS', line_numbers)
|
83
|
+
gsub!(/<\/div>\n/) { '</div>' }
|
84
|
+
gsub!(/\n/) { "<tt>\n</tt>" }
|
85
|
+
wrap_in! line_numbers_table_tpl
|
86
|
+
@wrapped_in = :div
|
87
|
+
|
88
|
+
when :list
|
89
|
+
opened_tags = []
|
90
|
+
gsub!(/^.*$\n?/) do |line|
|
91
|
+
line.chomp!
|
92
|
+
|
93
|
+
open = opened_tags.join
|
94
|
+
line.scan(%r!<(/)?span[^>]*>?!) do |close,|
|
95
|
+
if close
|
96
|
+
opened_tags.pop
|
97
|
+
else
|
98
|
+
opened_tags << $&
|
99
|
+
end
|
100
|
+
end
|
101
|
+
close = '</span>' * opened_tags.size
|
102
|
+
|
103
|
+
"<li>#{open}#{line}#{close}</li>\n"
|
104
|
+
end
|
105
|
+
chomp!("\n")
|
106
|
+
wrap_in! LIST
|
107
|
+
@wrapped_in = :div
|
108
|
+
|
109
|
+
else
|
110
|
+
raise ArgumentError, 'Unknown value %p for mode: expected one of %p' %
|
111
|
+
[mode, [:table, :list, :inline]]
|
112
|
+
end
|
113
|
+
|
114
|
+
self
|
115
|
+
end
|
116
|
+
|
117
|
+
def line_count
|
118
|
+
line_count = count("\n")
|
119
|
+
position_of_last_newline = rindex(?\n)
|
120
|
+
if position_of_last_newline
|
121
|
+
after_last_newline = self[position_of_last_newline + 1 .. -1]
|
122
|
+
ends_with_newline = after_last_newline[/\A(?:<\/span>)*\z/]
|
123
|
+
line_count += 1 if not ends_with_newline
|
124
|
+
end
|
125
|
+
line_count
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
module CodeRay
|
2
|
+
module Encoders
|
3
|
+
|
4
|
+
class HTML
|
5
|
+
|
6
|
+
# This module is included in the output String from thew HTML Encoder.
|
7
|
+
#
|
8
|
+
# It provides methods like wrap, div, page etc.
|
9
|
+
#
|
10
|
+
# Remember to use #clone instead of #dup to keep the modules the object was
|
11
|
+
# extended with.
|
12
|
+
#
|
13
|
+
# TODO: more doc.
|
14
|
+
module Output
|
15
|
+
|
16
|
+
require 'coderay/encoders/html/numerization.rb'
|
17
|
+
|
18
|
+
attr_accessor :css
|
19
|
+
|
20
|
+
class << self
|
21
|
+
|
22
|
+
# This makes Output look like a class.
|
23
|
+
#
|
24
|
+
# Example:
|
25
|
+
#
|
26
|
+
# a = Output.new '<span class="co">Code</span>'
|
27
|
+
# a.wrap! :page
|
28
|
+
def new string, css = CSS.new, element = nil
|
29
|
+
output = string.clone.extend self
|
30
|
+
output.wrapped_in = element
|
31
|
+
output.css = css
|
32
|
+
output
|
33
|
+
end
|
34
|
+
|
35
|
+
# Raises an exception if an object that doesn't respond to to_str is extended by Output,
|
36
|
+
# to prevent users from misuse. Use Module#remove_method to disable.
|
37
|
+
def extended o
|
38
|
+
warn "The Output module is intended to extend instances of String, not #{o.class}." unless o.respond_to? :to_str
|
39
|
+
end
|
40
|
+
|
41
|
+
def make_stylesheet css, in_tag = false
|
42
|
+
sheet = css.stylesheet
|
43
|
+
sheet = <<-CSS if in_tag
|
44
|
+
<style type="text/css">
|
45
|
+
#{sheet}
|
46
|
+
</style>
|
47
|
+
CSS
|
48
|
+
sheet
|
49
|
+
end
|
50
|
+
|
51
|
+
def page_template_for_css css
|
52
|
+
sheet = make_stylesheet css
|
53
|
+
PAGE.apply 'CSS', sheet
|
54
|
+
end
|
55
|
+
|
56
|
+
# Define a new wrapper. This is meta programming.
|
57
|
+
def wrapper *wrappers
|
58
|
+
wrappers.each do |wrapper|
|
59
|
+
define_method wrapper do |*args|
|
60
|
+
wrap wrapper, *args
|
61
|
+
end
|
62
|
+
define_method "#{wrapper}!".to_sym do |*args|
|
63
|
+
wrap! wrapper, *args
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
wrapper :div, :span, :page
|
71
|
+
|
72
|
+
def wrapped_in? element
|
73
|
+
wrapped_in == element
|
74
|
+
end
|
75
|
+
|
76
|
+
def wrapped_in
|
77
|
+
@wrapped_in ||= nil
|
78
|
+
end
|
79
|
+
attr_writer :wrapped_in
|
80
|
+
|
81
|
+
def wrap_in template
|
82
|
+
clone.wrap_in! template
|
83
|
+
end
|
84
|
+
|
85
|
+
def wrap_in! template
|
86
|
+
Template.wrap! self, template, 'CONTENT'
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
|
+
def apply_title! title
|
91
|
+
self.sub!(/(<title>)(<\/title>)/) { $1 + title + $2 }
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def wrap! element, *args
|
96
|
+
return self if not element or element == wrapped_in
|
97
|
+
case element
|
98
|
+
when :div
|
99
|
+
raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? nil
|
100
|
+
wrap_in! DIV
|
101
|
+
when :span
|
102
|
+
raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? nil
|
103
|
+
wrap_in! SPAN
|
104
|
+
when :page
|
105
|
+
wrap! :div if wrapped_in? nil
|
106
|
+
raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? :div
|
107
|
+
wrap_in! Output.page_template_for_css(@css)
|
108
|
+
if args.first.is_a?(Hash) && title = args.first[:title]
|
109
|
+
apply_title! title
|
110
|
+
end
|
111
|
+
self
|
112
|
+
when nil
|
113
|
+
return self
|
114
|
+
else
|
115
|
+
raise "Unknown value %p for :wrap" % element
|
116
|
+
end
|
117
|
+
@wrapped_in = element
|
118
|
+
self
|
119
|
+
end
|
120
|
+
|
121
|
+
def wrap *args
|
122
|
+
clone.wrap!(*args)
|
123
|
+
end
|
124
|
+
|
125
|
+
def stylesheet in_tag = false
|
126
|
+
Output.make_stylesheet @css, in_tag
|
127
|
+
end
|
128
|
+
|
129
|
+
class Template < String
|
130
|
+
|
131
|
+
def self.wrap! str, template, target
|
132
|
+
target = Regexp.new(Regexp.escape("<%#{target}%>"))
|
133
|
+
if template =~ target
|
134
|
+
str[0,0] = $`
|
135
|
+
str << $'
|
136
|
+
else
|
137
|
+
raise "Template target <%%%p%%> not found" % target
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def apply target, replacement
|
142
|
+
target = Regexp.new(Regexp.escape("<%#{target}%>"))
|
143
|
+
if self =~ target
|
144
|
+
Template.new($` + replacement + $')
|
145
|
+
else
|
146
|
+
raise "Template target <%%%p%%> not found" % target
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
module Simple
|
151
|
+
def ` str #` <-- for stupid editors
|
152
|
+
Template.new str
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
extend Template::Simple
|
158
|
+
|
159
|
+
#-- don't include the templates in docu
|
160
|
+
|
161
|
+
SPAN = `<span class="CodeRay"><%CONTENT%></span>`
|
162
|
+
|
163
|
+
DIV = <<-`DIV`
|
164
|
+
<div class="CodeRay">
|
165
|
+
<div class="code"><pre><%CONTENT%></pre></div>
|
166
|
+
</div>
|
167
|
+
DIV
|
168
|
+
|
169
|
+
TABLE = <<-`TABLE`
|
170
|
+
<table class="CodeRay"><tr>
|
171
|
+
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre><%LINE_NUMBERS%></pre></td>
|
172
|
+
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><%CONTENT%></pre></td>
|
173
|
+
</tr></table>
|
174
|
+
TABLE
|
175
|
+
# title="double click to expand"
|
176
|
+
|
177
|
+
LIST = <<-`LIST`
|
178
|
+
<ol class="CodeRay">
|
179
|
+
<%CONTENT%>
|
180
|
+
</ol>
|
181
|
+
LIST
|
182
|
+
|
183
|
+
PAGE = <<-`PAGE`
|
184
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
185
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
186
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="de">
|
187
|
+
<head>
|
188
|
+
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
189
|
+
<title></title>
|
190
|
+
<style type="text/css">
|
191
|
+
<%CSS%>
|
192
|
+
</style>
|
193
|
+
</head>
|
194
|
+
<body style="background-color: white;">
|
195
|
+
|
196
|
+
<%CONTENT%>
|
197
|
+
</body>
|
198
|
+
</html>
|
199
|
+
PAGE
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module CodeRay
|
2
|
+
module Encoders
|
3
|
+
|
4
|
+
# = JSON Encoder
|
5
|
+
class JSON < Encoder
|
6
|
+
|
7
|
+
register_for :json
|
8
|
+
FILE_EXTENSION = 'json'
|
9
|
+
|
10
|
+
protected
|
11
|
+
def compile tokens, options
|
12
|
+
require 'json'
|
13
|
+
@out = tokens.to_a.to_json
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module CodeRay
|
2
|
+
module Encoders
|
3
|
+
|
4
|
+
# = Null Encoder
|
5
|
+
#
|
6
|
+
# Does nothing and returns an empty string.
|
7
|
+
class Null < Encoder
|
8
|
+
|
9
|
+
include Streamable
|
10
|
+
register_for :null
|
11
|
+
|
12
|
+
# Defined for faster processing
|
13
|
+
def to_proc
|
14
|
+
proc {}
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def token(*)
|
20
|
+
# do nothing
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|