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,187 @@
|
|
1
|
+
require "stringio"
|
2
|
+
|
3
|
+
module CodeRay
|
4
|
+
|
5
|
+
# This module holds the Encoder class and its subclasses.
|
6
|
+
# For example, the HTML encoder is named CodeRay::Encoders::HTML
|
7
|
+
# can be found in coderay/encoders/html.
|
8
|
+
#
|
9
|
+
# Encoders also provides methods and constants for the register
|
10
|
+
# mechanism and the [] method that returns the Encoder class
|
11
|
+
# belonging to the given format.
|
12
|
+
module Encoders
|
13
|
+
extend PluginHost
|
14
|
+
plugin_path File.dirname(__FILE__), 'encoders'
|
15
|
+
|
16
|
+
# = Encoder
|
17
|
+
#
|
18
|
+
# The Encoder base class. Together with Scanner and
|
19
|
+
# Tokens, it forms the highlighting triad.
|
20
|
+
#
|
21
|
+
# Encoder instances take a Tokens object and do something with it.
|
22
|
+
#
|
23
|
+
# The most common Encoder is surely the HTML encoder
|
24
|
+
# (CodeRay::Encoders::HTML). It highlights the code in a colorful
|
25
|
+
# html page.
|
26
|
+
# If you want the highlighted code in a div or a span instead,
|
27
|
+
# use its subclasses Div and Span.
|
28
|
+
class Encoder
|
29
|
+
extend Plugin
|
30
|
+
plugin_host Encoders
|
31
|
+
|
32
|
+
attr_reader :token_stream
|
33
|
+
|
34
|
+
class << self
|
35
|
+
|
36
|
+
# Returns if the Encoder can be used in streaming mode.
|
37
|
+
def streamable?
|
38
|
+
is_a? Streamable
|
39
|
+
end
|
40
|
+
|
41
|
+
# If FILE_EXTENSION isn't defined, this method returns the
|
42
|
+
# downcase class name instead.
|
43
|
+
def const_missing sym
|
44
|
+
if sym == :FILE_EXTENSION
|
45
|
+
plugin_id
|
46
|
+
else
|
47
|
+
super
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
# Subclasses are to store their default options in this constant.
|
54
|
+
DEFAULT_OPTIONS = { :stream => false }
|
55
|
+
|
56
|
+
# The options you gave the Encoder at creating.
|
57
|
+
attr_accessor :options
|
58
|
+
|
59
|
+
# Creates a new Encoder.
|
60
|
+
# +options+ is saved and used for all encode operations, as long
|
61
|
+
# as you don't overwrite it there by passing additional options.
|
62
|
+
#
|
63
|
+
# Encoder objects provide three encode methods:
|
64
|
+
# - encode simply takes a +code+ string and a +lang+
|
65
|
+
# - encode_tokens expects a +tokens+ object instead
|
66
|
+
# - encode_stream is like encode, but uses streaming mode.
|
67
|
+
#
|
68
|
+
# Each method has an optional +options+ parameter. These are
|
69
|
+
# added to the options you passed at creation.
|
70
|
+
def initialize options = {}
|
71
|
+
@options = self.class::DEFAULT_OPTIONS.merge options
|
72
|
+
raise "I am only the basic Encoder class. I can't encode "\
|
73
|
+
"anything. :( Use my subclasses." if self.class == Encoder
|
74
|
+
end
|
75
|
+
|
76
|
+
# Encode a Tokens object.
|
77
|
+
def encode_tokens tokens, options = {}
|
78
|
+
options = @options.merge options
|
79
|
+
setup options
|
80
|
+
compile tokens, options
|
81
|
+
finish options
|
82
|
+
end
|
83
|
+
|
84
|
+
# Encode the given +code+ after tokenizing it using the Scanner
|
85
|
+
# for +lang+.
|
86
|
+
def encode code, lang, options = {}
|
87
|
+
options = @options.merge options
|
88
|
+
scanner_options = CodeRay.get_scanner_options(options)
|
89
|
+
tokens = CodeRay.scan code, lang, scanner_options
|
90
|
+
encode_tokens tokens, options
|
91
|
+
end
|
92
|
+
|
93
|
+
# You can use highlight instead of encode, if that seems
|
94
|
+
# more clear to you.
|
95
|
+
alias highlight encode
|
96
|
+
|
97
|
+
# Encode the given +code+ using the Scanner for +lang+ in
|
98
|
+
# streaming mode.
|
99
|
+
def encode_stream code, lang, options = {}
|
100
|
+
raise NotStreamableError, self unless kind_of? Streamable
|
101
|
+
options = @options.merge options
|
102
|
+
setup options
|
103
|
+
scanner_options = CodeRay.get_scanner_options options
|
104
|
+
@token_stream =
|
105
|
+
CodeRay.scan_stream code, lang, scanner_options, &self
|
106
|
+
finish options
|
107
|
+
end
|
108
|
+
|
109
|
+
# Behave like a proc. The token method is converted to a proc.
|
110
|
+
def to_proc
|
111
|
+
method(:token).to_proc
|
112
|
+
end
|
113
|
+
|
114
|
+
# Return the default file extension for outputs of this encoder.
|
115
|
+
def file_extension
|
116
|
+
self.class::FILE_EXTENSION
|
117
|
+
end
|
118
|
+
|
119
|
+
protected
|
120
|
+
|
121
|
+
# Called with merged options before encoding starts.
|
122
|
+
# Sets @out to an empty string.
|
123
|
+
#
|
124
|
+
# See the HTML Encoder for an example of option caching.
|
125
|
+
def setup options
|
126
|
+
@out = ''
|
127
|
+
end
|
128
|
+
|
129
|
+
# Called with +text+ and +kind+ of the currently scanned token.
|
130
|
+
# For simple scanners, it's enougth to implement this method.
|
131
|
+
#
|
132
|
+
# By default, it calls text_token or block_token, depending on
|
133
|
+
# whether +text+ is a String.
|
134
|
+
def token text, kind
|
135
|
+
out =
|
136
|
+
if text.is_a? ::String
|
137
|
+
text_token text, kind
|
138
|
+
elsif text.is_a? ::Symbol
|
139
|
+
block_token text, kind
|
140
|
+
else
|
141
|
+
raise 'Unknown token text type: %p' % text
|
142
|
+
end
|
143
|
+
@out << out if defined?(@out) && @out
|
144
|
+
end
|
145
|
+
|
146
|
+
def text_token text, kind
|
147
|
+
end
|
148
|
+
|
149
|
+
def block_token action, kind
|
150
|
+
case action
|
151
|
+
when :open
|
152
|
+
open_token kind
|
153
|
+
when :close
|
154
|
+
close_token kind
|
155
|
+
when :begin_line
|
156
|
+
begin_line kind
|
157
|
+
when :end_line
|
158
|
+
end_line kind
|
159
|
+
else
|
160
|
+
raise 'unknown block action: %p' % action
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# Called with merged options after encoding starts.
|
165
|
+
# The return value is the result of encoding, typically @out.
|
166
|
+
def finish options
|
167
|
+
@out
|
168
|
+
end
|
169
|
+
|
170
|
+
# Do the encoding.
|
171
|
+
#
|
172
|
+
# The already created +tokens+ object must be used; it can be a
|
173
|
+
# TokenStream or a Tokens object.
|
174
|
+
if RUBY_VERSION >= '1.9'
|
175
|
+
def compile tokens, options
|
176
|
+
tokens.each { |text, kind| token text, kind } # FIXME for Ruby 1.9?
|
177
|
+
end
|
178
|
+
else
|
179
|
+
def compile tokens, options
|
180
|
+
tokens.each(&self)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module CodeRay
|
2
|
+
module Encoders
|
3
|
+
|
4
|
+
# = Debug Encoder
|
5
|
+
#
|
6
|
+
# Fast encoder producing simple debug output.
|
7
|
+
#
|
8
|
+
# It is readable and diff-able and is used for testing.
|
9
|
+
#
|
10
|
+
# You cannot fully restore the tokens information from the
|
11
|
+
# output, because consecutive :space tokens are merged.
|
12
|
+
# Use Tokens#dump for caching purposes.
|
13
|
+
class Debug < Encoder
|
14
|
+
|
15
|
+
include Streamable
|
16
|
+
register_for :debug
|
17
|
+
|
18
|
+
FILE_EXTENSION = 'raydebug'
|
19
|
+
|
20
|
+
protected
|
21
|
+
def text_token text, kind
|
22
|
+
if kind == :space
|
23
|
+
text
|
24
|
+
else
|
25
|
+
text = text.gsub(/[)\\]/, '\\\\\0') # escape ) and \
|
26
|
+
"#{kind}(#{text})"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def open_token kind
|
31
|
+
"#{kind}<"
|
32
|
+
end
|
33
|
+
|
34
|
+
def close_token kind
|
35
|
+
">"
|
36
|
+
end
|
37
|
+
|
38
|
+
def begin_line kind
|
39
|
+
"#{kind}["
|
40
|
+
end
|
41
|
+
|
42
|
+
def end_line kind
|
43
|
+
"]"
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module CodeRay
|
2
|
+
module Encoders
|
3
|
+
|
4
|
+
load :html
|
5
|
+
|
6
|
+
class Div < HTML
|
7
|
+
|
8
|
+
FILE_EXTENSION = 'div.html'
|
9
|
+
|
10
|
+
register_for :div
|
11
|
+
|
12
|
+
DEFAULT_OPTIONS = HTML::DEFAULT_OPTIONS.merge({
|
13
|
+
:css => :style,
|
14
|
+
:wrap => :div,
|
15
|
+
})
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,306 @@
|
|
1
|
+
require "set"
|
2
|
+
|
3
|
+
module CodeRay
|
4
|
+
module Encoders
|
5
|
+
|
6
|
+
# = HTML Encoder
|
7
|
+
#
|
8
|
+
# This is CodeRay's most important highlighter:
|
9
|
+
# It provides save, fast XHTML generation and CSS support.
|
10
|
+
#
|
11
|
+
# == Usage
|
12
|
+
#
|
13
|
+
# require 'coderay'
|
14
|
+
# puts CodeRay.scan('Some /code/', :ruby).html #-> a HTML page
|
15
|
+
# puts CodeRay.scan('Some /code/', :ruby).html(:wrap => :span)
|
16
|
+
# #-> <span class="CodeRay"><span class="co">Some</span> /code/</span>
|
17
|
+
# puts CodeRay.scan('Some /code/', :ruby).span #-> the same
|
18
|
+
#
|
19
|
+
# puts CodeRay.scan('Some code', :ruby).html(
|
20
|
+
# :wrap => nil,
|
21
|
+
# :line_numbers => :inline,
|
22
|
+
# :css => :style
|
23
|
+
# )
|
24
|
+
# #-> <span class="no">1</span> <span style="color:#036; font-weight:bold;">Some</span> code
|
25
|
+
#
|
26
|
+
# == Options
|
27
|
+
#
|
28
|
+
# === :tab_width
|
29
|
+
# Convert \t characters to +n+ spaces (a number.)
|
30
|
+
# Default: 8
|
31
|
+
#
|
32
|
+
# === :css
|
33
|
+
# How to include the styles; can be :class or :style.
|
34
|
+
#
|
35
|
+
# Default: :class
|
36
|
+
#
|
37
|
+
# === :wrap
|
38
|
+
# Wrap in :page, :div, :span or nil.
|
39
|
+
#
|
40
|
+
# You can also use Encoders::Div and Encoders::Span.
|
41
|
+
#
|
42
|
+
# Default: nil
|
43
|
+
#
|
44
|
+
# === :title
|
45
|
+
#
|
46
|
+
# The title of the HTML page (works only when :wrap is set to :page.)
|
47
|
+
#
|
48
|
+
# Default: 'CodeRay output'
|
49
|
+
#
|
50
|
+
# === :line_numbers
|
51
|
+
# Include line numbers in :table, :inline, :list or nil (no line numbers)
|
52
|
+
#
|
53
|
+
# Default: nil
|
54
|
+
#
|
55
|
+
# === :line_number_start
|
56
|
+
# Where to start with line number counting.
|
57
|
+
#
|
58
|
+
# Default: 1
|
59
|
+
#
|
60
|
+
# === :bold_every
|
61
|
+
# Make every +n+-th number appear bold.
|
62
|
+
#
|
63
|
+
# Default: 10
|
64
|
+
#
|
65
|
+
# === :highlight_lines
|
66
|
+
#
|
67
|
+
# Highlights certain line numbers now by using the :highlight_lines option.
|
68
|
+
# Can be any Enumerable, typically just an Array or Range, of numbers.
|
69
|
+
#
|
70
|
+
# Bolding is deactivated when :highlight_lines is set. It only makes sense
|
71
|
+
# in combination with :line_numbers.
|
72
|
+
#
|
73
|
+
# Default: nil
|
74
|
+
#
|
75
|
+
# === :hint
|
76
|
+
# Include some information into the output using the title attribute.
|
77
|
+
# Can be :info (show token type on mouse-over), :info_long (with full path)
|
78
|
+
# or :debug (via inspect).
|
79
|
+
#
|
80
|
+
# Default: false
|
81
|
+
class HTML < Encoder
|
82
|
+
|
83
|
+
include Streamable
|
84
|
+
register_for :html
|
85
|
+
|
86
|
+
FILE_EXTENSION = 'html'
|
87
|
+
|
88
|
+
DEFAULT_OPTIONS = {
|
89
|
+
:tab_width => 8,
|
90
|
+
|
91
|
+
:level => :xhtml,
|
92
|
+
:css => :class,
|
93
|
+
|
94
|
+
:style => :cycnus,
|
95
|
+
:wrap => nil,
|
96
|
+
:title => 'CodeRay output',
|
97
|
+
|
98
|
+
:line_numbers => nil,
|
99
|
+
:line_number_start => 1,
|
100
|
+
:bold_every => 10,
|
101
|
+
:highlight_lines => nil,
|
102
|
+
|
103
|
+
:hint => false,
|
104
|
+
}
|
105
|
+
|
106
|
+
helper :output, :css
|
107
|
+
|
108
|
+
attr_reader :css
|
109
|
+
|
110
|
+
protected
|
111
|
+
|
112
|
+
HTML_ESCAPE = { #:nodoc:
|
113
|
+
'&' => '&',
|
114
|
+
'"' => '"',
|
115
|
+
'>' => '>',
|
116
|
+
'<' => '<',
|
117
|
+
}
|
118
|
+
|
119
|
+
# This was to prevent illegal HTML.
|
120
|
+
# Strange chars should still be avoided in codes.
|
121
|
+
evil_chars = Array(0x00...0x20) - [?\n, ?\t, ?\s]
|
122
|
+
evil_chars.each { |i| HTML_ESCAPE[i.chr] = ' ' }
|
123
|
+
#ansi_chars = Array(0x7f..0xff)
|
124
|
+
#ansi_chars.each { |i| HTML_ESCAPE[i.chr] = '&#%d;' % i }
|
125
|
+
# \x9 (\t) and \xA (\n) not included
|
126
|
+
#HTML_ESCAPE_PATTERN = /[\t&"><\0-\x8\xB-\x1f\x7f-\xff]/
|
127
|
+
HTML_ESCAPE_PATTERN = /[\t"&><\0-\x8\xB-\x1f]/
|
128
|
+
|
129
|
+
TOKEN_KIND_TO_INFO = Hash.new { |h, kind|
|
130
|
+
h[kind] =
|
131
|
+
case kind
|
132
|
+
when :pre_constant
|
133
|
+
'Predefined constant'
|
134
|
+
else
|
135
|
+
kind.to_s.gsub(/_/, ' ').gsub(/\b\w/) { $&.capitalize }
|
136
|
+
end
|
137
|
+
}
|
138
|
+
|
139
|
+
TRANSPARENT_TOKEN_KINDS = [
|
140
|
+
:delimiter, :modifier, :content, :escape, :inline_delimiter,
|
141
|
+
].to_set
|
142
|
+
|
143
|
+
# Generate a hint about the given +classes+ in a +hint+ style.
|
144
|
+
#
|
145
|
+
# +hint+ may be :info, :info_long or :debug.
|
146
|
+
def self.token_path_to_hint hint, classes
|
147
|
+
title =
|
148
|
+
case hint
|
149
|
+
when :info
|
150
|
+
TOKEN_KIND_TO_INFO[classes.first]
|
151
|
+
when :info_long
|
152
|
+
classes.reverse.map { |kind| TOKEN_KIND_TO_INFO[kind] }.join('/')
|
153
|
+
when :debug
|
154
|
+
classes.inspect
|
155
|
+
end
|
156
|
+
title ? " title=\"#{title}\"" : ''
|
157
|
+
end
|
158
|
+
|
159
|
+
def setup options
|
160
|
+
super
|
161
|
+
|
162
|
+
@HTML_ESCAPE = HTML_ESCAPE.dup
|
163
|
+
@HTML_ESCAPE["\t"] = ' ' * options[:tab_width]
|
164
|
+
|
165
|
+
@opened = [nil]
|
166
|
+
@css = CSS.new options[:style]
|
167
|
+
|
168
|
+
hint = options[:hint]
|
169
|
+
if hint and not [:debug, :info, :info_long].include? hint
|
170
|
+
raise ArgumentError, "Unknown value %p for :hint; \
|
171
|
+
expected :info, :debug, false, or nil." % hint
|
172
|
+
end
|
173
|
+
|
174
|
+
case options[:css]
|
175
|
+
|
176
|
+
when :class
|
177
|
+
@css_style = Hash.new do |h, k|
|
178
|
+
c = CodeRay::Tokens::ClassOfKind[k.first]
|
179
|
+
if c == :NO_HIGHLIGHT and not hint
|
180
|
+
h[k.dup] = false
|
181
|
+
else
|
182
|
+
title = if hint
|
183
|
+
HTML.token_path_to_hint(hint, k[1..-1] << k.first)
|
184
|
+
else
|
185
|
+
''
|
186
|
+
end
|
187
|
+
if c == :NO_HIGHLIGHT
|
188
|
+
h[k.dup] = '<span%s>' % [title]
|
189
|
+
else
|
190
|
+
h[k.dup] = '<span%s class="%s">' % [title, c]
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
when :style
|
196
|
+
@css_style = Hash.new do |h, k|
|
197
|
+
if k.is_a? ::Array
|
198
|
+
styles = k.dup
|
199
|
+
else
|
200
|
+
styles = [k]
|
201
|
+
end
|
202
|
+
type = styles.first
|
203
|
+
classes = styles.map { |c| Tokens::ClassOfKind[c] }
|
204
|
+
if classes.first == :NO_HIGHLIGHT and not hint
|
205
|
+
h[k] = false
|
206
|
+
else
|
207
|
+
styles.shift if TRANSPARENT_TOKEN_KINDS.include? styles.first
|
208
|
+
title = HTML.token_path_to_hint hint, styles
|
209
|
+
style = @css[*classes]
|
210
|
+
h[k] =
|
211
|
+
if style
|
212
|
+
'<span%s style="%s">' % [title, style]
|
213
|
+
else
|
214
|
+
false
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
else
|
220
|
+
raise ArgumentError, "Unknown value %p for :css." % options[:css]
|
221
|
+
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def finish options
|
226
|
+
not_needed = @opened.shift
|
227
|
+
@out << '</span>' * @opened.size
|
228
|
+
unless @opened.empty?
|
229
|
+
warn '%d tokens still open: %p' % [@opened.size, @opened]
|
230
|
+
end
|
231
|
+
|
232
|
+
@out.extend Output
|
233
|
+
@out.css = @css
|
234
|
+
@out.numerize! options[:line_numbers], options
|
235
|
+
@out.wrap! options[:wrap]
|
236
|
+
@out.apply_title! options[:title]
|
237
|
+
|
238
|
+
super
|
239
|
+
end
|
240
|
+
|
241
|
+
def token text, type = :plain
|
242
|
+
case text
|
243
|
+
|
244
|
+
when nil
|
245
|
+
# raise 'Token with nil as text was given: %p' % [[text, type]]
|
246
|
+
|
247
|
+
when String
|
248
|
+
if text =~ /#{HTML_ESCAPE_PATTERN}/o
|
249
|
+
text = text.gsub(/#{HTML_ESCAPE_PATTERN}/o) { |m| @HTML_ESCAPE[m] }
|
250
|
+
end
|
251
|
+
@opened[0] = type
|
252
|
+
if text != "\n" && style = @css_style[@opened]
|
253
|
+
@out << style << text << '</span>'
|
254
|
+
else
|
255
|
+
@out << text
|
256
|
+
end
|
257
|
+
|
258
|
+
|
259
|
+
# token groups, eg. strings
|
260
|
+
when :open
|
261
|
+
@opened[0] = type
|
262
|
+
@out << (@css_style[@opened] || '<span>')
|
263
|
+
@opened << type
|
264
|
+
when :close
|
265
|
+
if @opened.empty?
|
266
|
+
# nothing to close
|
267
|
+
else
|
268
|
+
if $DEBUG and (@opened.size == 1 or @opened.last != type)
|
269
|
+
raise 'Malformed token stream: Trying to close a token (%p) \
|
270
|
+
that is not open. Open are: %p.' % [type, @opened[1..-1]]
|
271
|
+
end
|
272
|
+
@out << '</span>'
|
273
|
+
@opened.pop
|
274
|
+
end
|
275
|
+
|
276
|
+
# whole lines to be highlighted, eg. a deleted line in a diff
|
277
|
+
when :begin_line
|
278
|
+
@opened[0] = type
|
279
|
+
if style = @css_style[@opened]
|
280
|
+
@out << style.sub('<span', '<div')
|
281
|
+
else
|
282
|
+
@out << '<div>'
|
283
|
+
end
|
284
|
+
@opened << type
|
285
|
+
when :end_line
|
286
|
+
if @opened.empty?
|
287
|
+
# nothing to close
|
288
|
+
else
|
289
|
+
if $DEBUG and (@opened.size == 1 or @opened.last != type)
|
290
|
+
raise 'Malformed token stream: Trying to close a line (%p) \
|
291
|
+
that is not open. Open are: %p.' % [type, @opened[1..-1]]
|
292
|
+
end
|
293
|
+
@out << '</div>'
|
294
|
+
@opened.pop
|
295
|
+
end
|
296
|
+
|
297
|
+
else
|
298
|
+
raise 'unknown token kind: %p' % [text]
|
299
|
+
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
end
|
304
|
+
|
305
|
+
end
|
306
|
+
end
|