rouge 1.11.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rouge.rb +5 -0
- data/lib/rouge/cli.rb +17 -6
- data/lib/rouge/formatter.rb +25 -0
- data/lib/rouge/formatters/html.rb +11 -88
- data/lib/rouge/formatters/html_inline.rb +22 -0
- data/lib/rouge/formatters/html_legacy.rb +44 -0
- data/lib/rouge/formatters/html_linewise.rb +27 -0
- data/lib/rouge/formatters/html_pygments.rb +16 -0
- data/lib/rouge/formatters/html_table.rb +61 -0
- data/lib/rouge/formatters/terminal256.rb +4 -8
- data/lib/rouge/plugins/redcarpet.rb +1 -1
- data/lib/rouge/version.rb +1 -1
- metadata +6 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53466ea8c28e8eaf9a27a2a850c2873033c8757b
|
4
|
+
data.tar.gz: ca08661ff885b0261350f79494eb0f80e41c0dd2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15aca0cf78e5b401fd871359748dbb49a5e61e6b476ad9918515e4ac07546659e3586e6a63f8023d4b9429591c72ce67983c4746e65473f3372ba64d3adfd6df
|
7
|
+
data.tar.gz: 683aa07c60241f925b0e90a5a6a881962b59bebebe4db6195fbf94ce7ebc687c48e2cb02c2cd26b46a4a2db59ece1128cda9c6fb48a370dddb2455abf4c64651
|
data/lib/rouge.rb
CHANGED
@@ -54,6 +54,11 @@ end
|
|
54
54
|
|
55
55
|
load load_dir.join('rouge/formatter.rb')
|
56
56
|
load load_dir.join('rouge/formatters/html.rb')
|
57
|
+
load load_dir.join('rouge/formatters/html_table.rb')
|
58
|
+
load load_dir.join('rouge/formatters/html_pygments.rb')
|
59
|
+
load load_dir.join('rouge/formatters/html_legacy.rb')
|
60
|
+
load load_dir.join('rouge/formatters/html_linewise.rb')
|
61
|
+
load load_dir.join('rouge/formatters/html_inline.rb')
|
57
62
|
load load_dir.join('rouge/formatters/terminal256.rb')
|
58
63
|
load load_dir.join('rouge/formatters/null.rb')
|
59
64
|
|
data/lib/rouge/cli.rb
CHANGED
@@ -181,6 +181,8 @@ module Rouge
|
|
181
181
|
def self.parse(argv)
|
182
182
|
opts = {
|
183
183
|
:formatter => 'terminal256',
|
184
|
+
:theme => 'thankful_eyes',
|
185
|
+
:css_class => 'codehilite',
|
184
186
|
:input_file => '-',
|
185
187
|
:lexer_opts => {},
|
186
188
|
:formatter_opts => {},
|
@@ -195,12 +197,14 @@ module Rouge
|
|
195
197
|
opts[:mimetype] = argv.shift
|
196
198
|
when '--lexer', '-l'
|
197
199
|
opts[:lexer] = argv.shift
|
198
|
-
when '--formatter', '-f'
|
200
|
+
when '--formatter-preset', '-f'
|
199
201
|
opts[:formatter] = argv.shift
|
202
|
+
when '--theme', '-t'
|
203
|
+
opts[:theme] = argv.shift
|
204
|
+
when '--css-class', '-c'
|
205
|
+
opts[:css_class] = argv.shift
|
200
206
|
when '--lexer-opts', '-L'
|
201
207
|
opts[:lexer_opts] = parse_cgi(argv.shift)
|
202
|
-
when '--formatter-opts', '-F'
|
203
|
-
opts[:formatter_opts] = parse_cgi(argv.shift)
|
204
208
|
when /^--/
|
205
209
|
error! "unknown option #{arg.inspect}"
|
206
210
|
else
|
@@ -246,10 +250,17 @@ module Rouge
|
|
246
250
|
|
247
251
|
@lexer_opts = opts[:lexer_opts]
|
248
252
|
|
249
|
-
|
250
|
-
or error! "unknown formatter #{opts[:formatter]}"
|
253
|
+
theme = Theme.find(opts[:theme]).new or error! "unknown theme #{opts[:theme]}"
|
251
254
|
|
252
|
-
@formatter =
|
255
|
+
@formatter = case opts[:formatter]
|
256
|
+
when 'terminal256' then Formatters::Terminal256.new(theme)
|
257
|
+
when 'html' then Formatters::HTML.new
|
258
|
+
when 'html-pygments' then Formatters::HTMLPygments.new(Formatters::HTML.new, opts[:css_class])
|
259
|
+
when 'html-inline' then Formatters::HTMLInline.new(theme)
|
260
|
+
when 'html-table' then Formatters::HTMLTable.new(Formatters::HTML.new)
|
261
|
+
else
|
262
|
+
error! "unknown formatter preset #{opts[:formatter]}"
|
263
|
+
end
|
253
264
|
end
|
254
265
|
|
255
266
|
def run
|
data/lib/rouge/formatter.rb
CHANGED
@@ -25,6 +25,10 @@ module Rouge
|
|
25
25
|
new(opts).format(tokens, &b)
|
26
26
|
end
|
27
27
|
|
28
|
+
def initialize(opts={})
|
29
|
+
# pass
|
30
|
+
end
|
31
|
+
|
28
32
|
# Format a token stream.
|
29
33
|
def format(tokens, &b)
|
30
34
|
return stream(tokens, &b) if block_given?
|
@@ -46,5 +50,26 @@ module Rouge
|
|
46
50
|
def stream(tokens, &b)
|
47
51
|
raise 'abstract'
|
48
52
|
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
def token_lines(tokens, &b)
|
56
|
+
return enum_for(:lines, tokens) unless block_given?
|
57
|
+
|
58
|
+
out = []
|
59
|
+
tokens.each do |tok, val|
|
60
|
+
val.scan /\n|[^\n]+/ do |s|
|
61
|
+
if s == "\n"
|
62
|
+
yield out
|
63
|
+
out = []
|
64
|
+
else
|
65
|
+
out << [tok, s]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# for inputs not ending in a newline
|
71
|
+
yield out if out.any?
|
72
|
+
end
|
73
|
+
|
49
74
|
end
|
50
75
|
end
|
@@ -9,109 +9,32 @@ module Rouge
|
|
9
9
|
class HTML < Formatter
|
10
10
|
tag 'html'
|
11
11
|
|
12
|
-
# @option opts [String] :css_class ('highlight')
|
13
|
-
# @option opts [true/false] :line_numbers (false)
|
14
|
-
# @option opts [Rouge::CSSTheme] :inline_theme (nil)
|
15
|
-
# @option opts [true/false] :wrap (true)
|
16
|
-
#
|
17
|
-
# Initialize with options.
|
18
|
-
#
|
19
|
-
# If `:inline_theme` is given, then instead of rendering the
|
20
|
-
# tokens as <span> tags with CSS classes, the styles according to
|
21
|
-
# the given theme will be inlined in "style" attributes. This is
|
22
|
-
# useful for formats in which stylesheets are not available.
|
23
|
-
#
|
24
|
-
# Content will be wrapped in a tag (`div` if tableized, `pre` if
|
25
|
-
# not) with the given `:css_class` unless `:wrap` is set to `false`.
|
26
|
-
def initialize(opts={})
|
27
|
-
@css_class = opts.fetch(:css_class, 'highlight')
|
28
|
-
@css_class = " class=#{@css_class.inspect}" if @css_class
|
29
|
-
|
30
|
-
@line_numbers = opts.fetch(:line_numbers, false)
|
31
|
-
@start_line = opts.fetch(:start_line, 1)
|
32
|
-
@inline_theme = opts.fetch(:inline_theme, nil)
|
33
|
-
@inline_theme = Theme.find(@inline_theme).new if @inline_theme.is_a? String
|
34
|
-
|
35
|
-
@wrap = opts.fetch(:wrap, true)
|
36
|
-
end
|
37
|
-
|
38
12
|
# @yield the html output.
|
39
13
|
def stream(tokens, &b)
|
40
|
-
|
41
|
-
stream_tableized(tokens, &b)
|
42
|
-
else
|
43
|
-
stream_untableized(tokens, &b)
|
44
|
-
end
|
14
|
+
tokens.each { |tok, val| yield span(tok, val) }
|
45
15
|
end
|
46
16
|
|
47
|
-
|
48
|
-
|
49
|
-
yield "<pre#@css_class><code>" if @wrap
|
50
|
-
tokens.each{ |tok, val| span(tok, val, &b) }
|
51
|
-
yield "</code></pre>\n" if @wrap
|
17
|
+
def span(tok, val)
|
18
|
+
safe_span(tok, val.gsub(/[&<>]/, TABLE_FOR_ESCAPE_HTML))
|
52
19
|
end
|
53
20
|
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
last_val = val
|
61
|
-
num_lines += val.scan(/\n/).size
|
62
|
-
span(tok, val) { |str| formatted << str }
|
63
|
-
end
|
21
|
+
def safe_span(tok, safe_val)
|
22
|
+
if tok == Token::Tokens::Text
|
23
|
+
safe_val
|
24
|
+
else
|
25
|
+
shortname = tok.shortname \
|
26
|
+
or raise "unknown token: #{tok.inspect} for #{safe_val.inspect}"
|
64
27
|
|
65
|
-
|
66
|
-
if last_val[-1] != "\n"
|
67
|
-
num_lines += 1
|
68
|
-
span(Token::Tokens::Text::Whitespace, "\n") { |str| formatted << str }
|
28
|
+
"<span class=\"#{shortname}\">#{safe_val}</span>"
|
69
29
|
end
|
70
|
-
|
71
|
-
# generate a string of newline-separated line numbers for the gutter>
|
72
|
-
numbers = %<<pre class="lineno">#{(@start_line..num_lines+@start_line-1)
|
73
|
-
.to_a.join("\n")}</pre>>
|
74
|
-
|
75
|
-
yield "<div#@css_class>" if @wrap
|
76
|
-
yield '<table style="border-spacing: 0"><tbody><tr>'
|
77
|
-
|
78
|
-
# the "gl" class applies the style for Generic.Lineno
|
79
|
-
yield '<td class="gutter gl" style="text-align: right">'
|
80
|
-
yield numbers
|
81
|
-
yield '</td>'
|
82
|
-
|
83
|
-
yield '<td class="code">'
|
84
|
-
yield '<pre>'
|
85
|
-
yield formatted
|
86
|
-
yield '</pre>'
|
87
|
-
yield '</td>'
|
88
|
-
|
89
|
-
yield "</tr></tbody></table>\n"
|
90
|
-
yield "</div>\n" if @wrap
|
91
30
|
end
|
92
31
|
|
32
|
+
private
|
93
33
|
TABLE_FOR_ESCAPE_HTML = {
|
94
34
|
'&' => '&',
|
95
35
|
'<' => '<',
|
96
36
|
'>' => '>',
|
97
37
|
}
|
98
|
-
|
99
|
-
def span(tok, val)
|
100
|
-
val = val.gsub(/[&<>]/, TABLE_FOR_ESCAPE_HTML)
|
101
|
-
shortname = tok.shortname or raise "unknown token: #{tok.inspect} for #{val.inspect}"
|
102
|
-
|
103
|
-
if shortname.empty?
|
104
|
-
yield val
|
105
|
-
else
|
106
|
-
if @inline_theme
|
107
|
-
rules = @inline_theme.style_for(tok).rendered_rules
|
108
|
-
|
109
|
-
yield "<span style=\"#{rules.to_a.join(';')}\">#{val}</span>"
|
110
|
-
else
|
111
|
-
yield "<span class=\"#{shortname}\">#{val}</span>"
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
38
|
end
|
116
39
|
end
|
117
40
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- coding: utf-8 -*- #
|
2
|
+
|
3
|
+
module Rouge
|
4
|
+
module Formatters
|
5
|
+
class HTMLInline < HTML
|
6
|
+
tag 'html_inline'
|
7
|
+
|
8
|
+
def initialize(theme)
|
9
|
+
@theme = theme
|
10
|
+
end
|
11
|
+
|
12
|
+
def safe_span(tok, safe_val)
|
13
|
+
return safe_val if tok == Token::Tokens::Text
|
14
|
+
|
15
|
+
rules = @theme.style_for(tok).rendered_rules
|
16
|
+
|
17
|
+
"<span style=\"#{rules.to_a.join(';')}\">#{safe_val}</span>"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# -*- coding: utf-8 -*- #
|
2
|
+
|
3
|
+
# stdlib
|
4
|
+
require 'cgi'
|
5
|
+
|
6
|
+
module Rouge
|
7
|
+
module Formatters
|
8
|
+
# Transforms a token stream into HTML output.
|
9
|
+
class HTMLLegacy < Formatter
|
10
|
+
tag 'html_legacy'
|
11
|
+
|
12
|
+
# @option opts [String] :css_class ('highlight')
|
13
|
+
# @option opts [true/false] :line_numbers (false)
|
14
|
+
# @option opts [Rouge::CSSTheme] :inline_theme (nil)
|
15
|
+
# @option opts [true/false] :wrap (true)
|
16
|
+
#
|
17
|
+
# Initialize with options.
|
18
|
+
#
|
19
|
+
# If `:inline_theme` is given, then instead of rendering the
|
20
|
+
# tokens as <span> tags with CSS classes, the styles according to
|
21
|
+
# the given theme will be inlined in "style" attributes. This is
|
22
|
+
# useful for formats in which stylesheets are not available.
|
23
|
+
#
|
24
|
+
# Content will be wrapped in a tag (`div` if tableized, `pre` if
|
25
|
+
# not) with the given `:css_class` unless `:wrap` is set to `false`.
|
26
|
+
def initialize(opts={})
|
27
|
+
@formatter = opts[:inline_theme] ? HTMLInline.new(opts[:inline_theme])
|
28
|
+
: HTML.new
|
29
|
+
|
30
|
+
|
31
|
+
@formatter = HTMLTable.new(@formatter, opts) if opts[:line_numbers]
|
32
|
+
|
33
|
+
if opts.fetch(:wrap, true)
|
34
|
+
@formatter = HTMLPygments.new(@formatter, opts.fetch(:css_class, 'codehilite'))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# @yield the html output.
|
39
|
+
def stream(tokens, &b)
|
40
|
+
@formatter.stream(tokens, &b)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- coding: utf-8 -*- #
|
2
|
+
|
3
|
+
module Rouge
|
4
|
+
module Formatters
|
5
|
+
class HTMLLinewise < Formatter
|
6
|
+
def initialize(formatter, opts={})
|
7
|
+
@formatter = formatter
|
8
|
+
@class_format = opts.fetch(:class, 'line-%i')
|
9
|
+
end
|
10
|
+
|
11
|
+
def stream(tokens, &b)
|
12
|
+
token_lines(tokens) do |line|
|
13
|
+
yield "<div class=#{next_line_class}>"
|
14
|
+
line.each do |tok, val|
|
15
|
+
yield @formatter.span(tok, val)
|
16
|
+
end
|
17
|
+
yield '</div>'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def next_line_class
|
22
|
+
@lineno ||= 0
|
23
|
+
sprintf(@class_format, @lineno += 1).inspect
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Rouge
|
2
|
+
module Formatters
|
3
|
+
class HTMLPygments < Formatter
|
4
|
+
def initialize(inner, css_class='codehilite')
|
5
|
+
@inner = inner
|
6
|
+
@css_class = css_class
|
7
|
+
end
|
8
|
+
|
9
|
+
def stream(tokens, &b)
|
10
|
+
yield %<<pre class="#@css_class"><code>>
|
11
|
+
@inner.stream(tokens, &b)
|
12
|
+
yield "</code></pre>"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# -*- coding: utf-8 -*- #
|
2
|
+
|
3
|
+
module Rouge
|
4
|
+
module Formatters
|
5
|
+
class HTMLTable < Formatter
|
6
|
+
tag 'html_table'
|
7
|
+
|
8
|
+
def initialize(inner, opts={})
|
9
|
+
@inner = inner
|
10
|
+
@start_line = opts.fetch(:start_line, 1)
|
11
|
+
@line_format = opts.fetch(:line_format, '%i')
|
12
|
+
@table_class = opts.fetch(:table_class, 'rouge-table')
|
13
|
+
@gutter_class = opts.fetch(:gutter_class, 'rouge-gutter')
|
14
|
+
@code_class = opts.fetch(:code_class, 'rouge-code')
|
15
|
+
end
|
16
|
+
|
17
|
+
def style(scope)
|
18
|
+
yield "#{scope} .rouge-table { border-spacing: 0 }"
|
19
|
+
yield "#{scope} .rouge-gutter { text-align: right }"
|
20
|
+
end
|
21
|
+
|
22
|
+
def stream(tokens, &b)
|
23
|
+
num_lines = 0
|
24
|
+
last_val = ''
|
25
|
+
formatted = ''
|
26
|
+
|
27
|
+
tokens.each do |tok, val|
|
28
|
+
last_val = val
|
29
|
+
num_lines += val.scan(/\n/).size
|
30
|
+
formatted << @inner.span(tok, val)
|
31
|
+
end
|
32
|
+
|
33
|
+
# add an extra line for non-newline-terminated strings
|
34
|
+
if last_val[-1] != "\n"
|
35
|
+
num_lines += 1
|
36
|
+
@inner.span(Token::Tokens::Text::Whitespace, "\n") { |str| formatted << str }
|
37
|
+
end
|
38
|
+
|
39
|
+
# generate a string of newline-separated line numbers for the gutter>
|
40
|
+
formatted_line_numbers = (@start_line..num_lines+@start_line-1).map do |i|
|
41
|
+
sprintf("#{@line_format}", i) << "\n"
|
42
|
+
end.join('')
|
43
|
+
|
44
|
+
numbers = %<<pre class="lineno">#{formatted_line_numbers}</pre>>
|
45
|
+
|
46
|
+
yield %<<table class="#@table_class"><tbody><tr>>
|
47
|
+
|
48
|
+
# the "gl" class applies the style for Generic.Lineno
|
49
|
+
yield %<<td class="#@gutter_class gl">>
|
50
|
+
yield numbers
|
51
|
+
yield '</td>'
|
52
|
+
|
53
|
+
yield %<<td class="#@code_class"><pre>>
|
54
|
+
yield formatted
|
55
|
+
yield '</pre></td>'
|
56
|
+
|
57
|
+
yield "</tr></tbody></table>\n"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -4,17 +4,13 @@ module Rouge
|
|
4
4
|
module Formatters
|
5
5
|
# A formatter for 256-color terminals
|
6
6
|
class Terminal256 < Formatter
|
7
|
-
tag 'terminal256'
|
8
|
-
|
9
7
|
# @private
|
10
8
|
attr_reader :theme
|
11
9
|
|
12
|
-
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
@theme = opts[:theme] || 'thankful_eyes'
|
17
|
-
@theme = Theme.find(@theme) if @theme.is_a? String
|
10
|
+
# @argument theme
|
11
|
+
# the theme to render with.
|
12
|
+
def initialize(theme=nil)
|
13
|
+
@theme = theme || Themes::ThankfulEyes
|
18
14
|
end
|
19
15
|
|
20
16
|
def stream(tokens, &b)
|
data/lib/rouge/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rouge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeanine Adkisson
|
@@ -126,6 +126,11 @@ files:
|
|
126
126
|
- lib/rouge/demos/yaml
|
127
127
|
- lib/rouge/formatter.rb
|
128
128
|
- lib/rouge/formatters/html.rb
|
129
|
+
- lib/rouge/formatters/html_inline.rb
|
130
|
+
- lib/rouge/formatters/html_legacy.rb
|
131
|
+
- lib/rouge/formatters/html_linewise.rb
|
132
|
+
- lib/rouge/formatters/html_pygments.rb
|
133
|
+
- lib/rouge/formatters/html_table.rb
|
129
134
|
- lib/rouge/formatters/null.rb
|
130
135
|
- lib/rouge/formatters/terminal256.rb
|
131
136
|
- lib/rouge/guesser.rb
|