Skip to content

Commit d68749d

Browse files
committed
Merge remote-tracking branch 'emassip/master' into independent-lines
2 parents 36b1799 + ce3a6c7 commit d68749d

File tree

3 files changed

+134
-19
lines changed

3 files changed

+134
-19
lines changed

lib/coderay/encoders/html.rb

+28-5
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ module Encoders
4747
#
4848
# Default: 'CodeRay output'
4949
#
50+
# === :independent_lines
51+
# Split multilines blocks into line-wide blocks.
52+
# Forced to true if :line_numbers option is set to :inline.
53+
#
54+
# Default: false
55+
#
5056
# === :line_numbers
5157
# Include line numbers in :table, :inline, or nil (no line numbers)
5258
#
@@ -99,7 +105,8 @@ class HTML < Encoder
99105
:style => :alpha,
100106
:wrap => nil,
101107
:title => 'CodeRay output',
102-
108+
109+
:independent_lines => false,
103110
:line_numbers => nil,
104111
:line_number_anchors => 'n',
105112
:line_number_start => 1,
@@ -167,7 +174,11 @@ def setup options
167174
@real_out = @out
168175
@out = ''
169176
end
170-
177+
178+
options[:independent_lines] = true if options[:line_numbers] == :inline
179+
180+
@independent_lines = (options[:independent_lines] == true)
181+
171182
@HTML_ESCAPE = HTML_ESCAPE.dup
172183
@HTML_ESCAPE["\t"] = ' ' * options[:tab_width]
173184

@@ -245,13 +256,25 @@ def text_token text, kind
245256
if text =~ /#{HTML_ESCAPE_PATTERN}/o
246257
text = text.gsub(/#{HTML_ESCAPE_PATTERN}/o) { |m| @HTML_ESCAPE[m] }
247258
end
248-
if style = @span_for_kind[@last_opened ? [kind, *@opened] : kind]
259+
260+
style = @span_for_kind[@last_opened ? [kind, *@opened] : kind]
261+
262+
if @independent_lines && (i = text.index("\n")) && (c = @opened.size + (style ? 1 : 0)) > 0
263+
close = '</span>' * c
264+
reopen = ''
265+
@opened.each_with_index do |k, index|
266+
reopen << (@span_for_kind[index > 0 ? [k, *@opened[0 ... index ]] : k] || '<span>')
267+
end
268+
text[i .. -1] = text[i .. -1].gsub("\n", "#{close}\n#{reopen}#{style}")
269+
end
270+
271+
if style
249272
@out << style << text << '</span>'
250273
else
251274
@out << text
252275
end
253276
end
254-
277+
255278
# token groups, eg. strings
256279
def begin_group kind
257280
@out << (@span_for_kind[@last_opened ? [kind, *@opened] : kind] || '<span>')
@@ -299,4 +322,4 @@ def end_line kind
299322
end
300323

301324
end
302-
end
325+
end

lib/coderay/encoders/html/numbering.rb

+2-14
Original file line numberDiff line numberDiff line change
@@ -68,23 +68,11 @@ def self.number! output, mode = :table, options = {}
6868
when :inline
6969
max_width = (start + line_count).to_s.size
7070
line_number = start
71-
nesting = []
7271
output.gsub!(/^.*$\n?/) do |line|
73-
line.chomp!
74-
open = nesting.join
75-
line.scan(%r!<(/)?span[^>]*>?!) do |close,|
76-
if close
77-
nesting.pop
78-
else
79-
nesting << $&
80-
end
81-
end
82-
close = '</span>' * nesting.size
83-
8472
line_number_text = bolding.call line_number
8573
indent = ' ' * (max_width - line_number.to_s.size) # TODO: Optimize (10^x)
8674
line_number += 1
87-
"<span class=\"line-numbers\">#{indent}#{line_number_text}</span>#{open}#{line}#{close}\n"
75+
"<span class=\"line-numbers\">#{indent}#{line_number_text}</span>#{line}"
8876
end
8977

9078
when :table
@@ -112,4 +100,4 @@ def self.number! output, mode = :table, options = {}
112100
end
113101

114102
end
115-
end
103+
end

test/unit/html.rb

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
require 'test/unit'
2+
require 'coderay'
3+
4+
class HtmlTest < Test::Unit::TestCase
5+
6+
def test_independent_lines_option
7+
8+
snippets = {}
9+
10+
snippets[:ruby] = {}
11+
12+
snippets[:ruby][:in] = <<-RUBY
13+
ruby_inside = <<-RUBY_INSIDE
14+
This is tricky,
15+
isn't it?
16+
RUBY_INSIDE
17+
RUBY
18+
19+
snippets[:ruby][:expected_with_option_off] = <<-HTML_OPT_INDEPENDENT_LINES_OFF
20+
ruby_inside = <span class=\"string\"><span class=\"delimiter\">&lt;&lt;-RUBY_INSIDE</span></span><span class=\"string\"><span class=\"content\">
21+
This is tricky,
22+
isn't it?</span><span class=\"delimiter\">
23+
RUBY_INSIDE</span></span>
24+
HTML_OPT_INDEPENDENT_LINES_OFF
25+
26+
snippets[:ruby][:expected_with_option_on] = <<-HTML_OPT_INDEPENDENT_LINES_ON
27+
ruby_inside = <span class=\"string\"><span class=\"delimiter\">&lt;&lt;-RUBY_INSIDE</span></span><span class=\"string\"><span class=\"content\"></span></span>
28+
<span class=\"string\"><span class=\"content\">This is tricky,</span></span>
29+
<span class=\"string\"><span class=\"content\">isn't it?</span><span class=\"delimiter\"></span></span>
30+
<span class=\"string\"><span class=\"delimiter\">RUBY_INSIDE</span></span>
31+
HTML_OPT_INDEPENDENT_LINES_ON
32+
33+
snippets[:java] = {}
34+
35+
snippets[:java][:in] = <<-JAVA
36+
import java.lang.*;
37+
38+
/**
39+
* This is some multiline javadoc
40+
* used to test the
41+
*/
42+
public class Test {
43+
public static final String MESSAGE = "My message\
44+
To the world";
45+
46+
static void main() {
47+
/*
48+
* Another multiline
49+
* comment
50+
*/
51+
System.out.println(MESSAGE);
52+
}
53+
}
54+
JAVA
55+
56+
snippets[:java][:expected_with_option_off] = <<-HTML_OPT_INDEPENDENT_LINES_OFF
57+
<span class=\"keyword\">import</span> <span class=\"include\">java.lang</span>.*;
58+
59+
<span class=\"comment\">/**
60+
* This is some multiline javadoc
61+
* used to test the
62+
*/</span>
63+
<span class=\"directive\">public</span> <span class=\"type\">class</span> <span class=\"class\">Test</span> {
64+
<span class=\"directive\">public</span> <span class=\"directive\">static</span> <span class=\"directive\">final</span> <span class=\"predefined-type\">String</span> MESSAGE = <span class=\"string\"><span class=\"delimiter\">&quot;</span><span class=\"content\">My message To the world</span><span class=\"delimiter\">&quot;</span></span>;
65+
66+
<span class=\"directive\">static</span> <span class=\"type\">void</span> main() {
67+
<span class=\"comment\">/*
68+
* Another multiline
69+
* comment
70+
*/</span>
71+
<span class=\"predefined-type\">System</span>.out.println(MESSAGE);
72+
}
73+
}
74+
HTML_OPT_INDEPENDENT_LINES_OFF
75+
76+
snippets[:java][:expected_with_option_on] = <<-HTML_OPT_INDEPENDENT_LINES_ON
77+
<span class=\"keyword\">import</span> <span class=\"include\">java.lang</span>.*;
78+
79+
<span class=\"comment\">/**</span>
80+
<span class=\"comment\"> * This is some multiline javadoc</span>
81+
<span class=\"comment\"> * used to test the</span>
82+
<span class=\"comment\"> */</span>
83+
<span class=\"directive\">public</span> <span class=\"type\">class</span> <span class=\"class\">Test</span> {
84+
<span class=\"directive\">public</span> <span class=\"directive\">static</span> <span class=\"directive\">final</span> <span class=\"predefined-type\">String</span> MESSAGE = <span class=\"string\"><span class=\"delimiter\">&quot;</span><span class=\"content\">My message To the world</span><span class=\"delimiter\">&quot;</span></span>;
85+
86+
<span class=\"directive\">static</span> <span class=\"type\">void</span> main() {
87+
<span class=\"comment\">/*</span>
88+
<span class=\"comment\"> * Another multiline</span>
89+
<span class=\"comment\"> * comment</span>
90+
<span class=\"comment\"> */</span>
91+
<span class=\"predefined-type\">System</span>.out.println(MESSAGE);
92+
}
93+
}
94+
HTML_OPT_INDEPENDENT_LINES_ON
95+
96+
snippets.entries().each do |lang, code|
97+
tokens = CodeRay.scan code[:in], lang
98+
99+
assert_equal code[:expected_with_option_off], tokens.html
100+
assert_equal code[:expected_with_option_off], tokens.html(:independent_lines => false)
101+
assert_equal code[:expected_with_option_on], tokens.html(:independent_lines => true)
102+
end
103+
end
104+
end

0 commit comments

Comments
 (0)