| Module | CodeRay::Encoders::HTML::Output |
| In: |
lib/coderay/encoders/html/numerization.rb
lib/coderay/encoders/html/output.rb |
| SPAN | = | `<span class="CodeRay"><%CONTENT%></span>` | ||
| DIV | = | <<-`DIV` <div class="CodeRay"> <div class="code"><pre><%CONTENT%></pre></div> </div> DIV | ||
| TABLE | = | <<-`TABLE` <table class="CodeRay"><tr> <td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre><%LINE_NUMBERS%></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><%CONTENT%></pre></td> </tr></table> TABLE | ||
| LIST | = | <<-`LIST` <ol class="CodeRay"> <%CONTENT%> </ol> LIST | title="double click to expand" | |
| PAGE | = | <<-`PAGE` <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="de"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>CodeRay Output</title> <style type="text/css"> <%CSS%> </style> </head> <body style="background-color: white;"> <%CONTENT%> </body> </html> PAGE |
| css | [RW] | |
| wrapped_in | [W] |
Raises an exception if an object that doesn‘t respond to to_str is extended by Output, to prevent users from misuse. Use Module#remove_method to disable.
# File lib/coderay/encoders/html/output.rb, line 37
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
# File lib/coderay/encoders/html/output.rb, line 41
41: def make_stylesheet css, in_tag = false
42: sheet = css.stylesheet
43: sheet = "<style type=\"text/css\">\n\#{sheet}\n</style>\n" if in_tag
44: sheet
45: end
This makes Output look like a class.
Example:
a = Output.new '<span class="co">Code</span>' a.wrap! :page
# File lib/coderay/encoders/html/output.rb, line 28
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
# File lib/coderay/encoders/html/output.rb, line 52
52: def page_template_for_css css
53: sheet = make_stylesheet css
54: PAGE.apply 'CSS', sheet
55: end
Define a new wrapper. This is meta programming.
# File lib/coderay/encoders/html/output.rb, line 58
58: def wrapper *wrappers
59: wrappers.each do |wrapper|
60: define_method wrapper do |*args|
61: wrap wrapper, *args
62: end
63: define_method "#{wrapper}!".to_sym do |*args|
64: wrap! wrapper, *args
65: end
66: end
67: end
# File lib/coderay/encoders/html/numerization.rb, line 108
108: def line_count
109: line_count = count("\n")
110: position_of_last_newline = rindex(?\n)
111: if position_of_last_newline
112: after_last_newline = self[position_of_last_newline + 1 .. -1]
113: ends_with_newline = after_last_newline[/\A(?:<\/span>)*\z/]
114: line_count += 1 if not ends_with_newline
115: end
116: line_count
117: end
# File lib/coderay/encoders/html/numerization.rb, line 8
8: def numerize *args
9: clone.numerize!(*args)
10: end
# File lib/coderay/encoders/html/numerization.rb, line 19
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: bolding =
36: if bold_every == false
37: proc { |line| line.to_s }
38: elsif bold_every.is_a? Integer
39: raise ArgumentError, ":bolding can't be 0." if bold_every == 0
40: proc do |line|
41: if line % bold_every == 0
42: "<strong>#{line}</strong>" # every bold_every-th number in bold
43: else
44: line.to_s
45: end
46: end
47: else
48: raise ArgumentError, 'Invalid value %p for :bolding; false or Integer expected.' % bold_every
49: end
50:
51: case mode
52: when :inline
53: max_width = (start + line_count).to_s.size
54: line_number = start
55: gsub!(/^/) do
56: line_number_text = bolding.call line_number
57: indent = ' ' * (max_width - line_number.to_s.size) # TODO: Optimize (10^x)
58: res = "<span class=\"no\">#{indent}#{line_number_text}</span> "
59: line_number += 1
60: res
61: end
62:
63: when :table
64: # This is really ugly.
65: # Because even monospace fonts seem to have different heights when bold,
66: # I make the newline bold, both in the code and the line numbers.
67: # FIXME Still not working perfect for Mr. Internet Exploder
68: # FIXME Firefox struggles with very long codes (> 200 lines)
69: line_numbers = (start ... start + line_count).to_a.map(&bolding).join("\n")
70: line_numbers << "\n" # also for Mr. MS Internet Exploder :-/
71: line_numbers.gsub!(/\n/) { "<tt>\n</tt>" }
72:
73: line_numbers_table_tpl = TABLE.apply('LINE_NUMBERS', line_numbers)
74: gsub!(/<\/div>\n/) { '</div>' }
75: gsub!(/\n/) { "<tt>\n</tt>" }
76: wrap_in! line_numbers_table_tpl
77: @wrapped_in = :div
78:
79: when :list
80: opened_tags = []
81: gsub!(/^.*$\n?/) do |line|
82: line.chomp!
83:
84: open = opened_tags.join
85: line.scan(%r!<(/)?span[^>]*>?!) do |close,|
86: if close
87: opened_tags.pop
88: else
89: opened_tags << $&
90: end
91: end
92: close = '</span>' * opened_tags.size
93:
94: "<li>#{open}#{line}#{close}</li>\n"
95: end
96: chomp!("\n")
97: wrap_in! LIST
98: @wrapped_in = :div
99:
100: else
101: raise ArgumentError, 'Unknown value %p for mode: expected one of %p' %
102: [mode, [:table, :list, :inline]]
103: end
104:
105: self
106: end
# File lib/coderay/encoders/html/output.rb, line 117
117: def stylesheet in_tag = false
118: Output.make_stylesheet @css, in_tag
119: end
# File lib/coderay/encoders/html/output.rb, line 113
113: def wrap *args
114: clone.wrap!(*args)
115: end
# File lib/coderay/encoders/html/output.rb, line 91
91: def wrap! element, *args
92: return self if not element or element == wrapped_in
93: case element
94: when :div
95: raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? nil
96: wrap_in! DIV
97: when :span
98: raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? nil
99: wrap_in! SPAN
100: when :page
101: wrap! :div if wrapped_in? nil
102: raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? :div
103: wrap_in! Output.page_template_for_css(@css)
104: when nil
105: return self
106: else
107: raise "Unknown value %p for :wrap" % element
108: end
109: @wrapped_in = element
110: self
111: end
# File lib/coderay/encoders/html/output.rb, line 82
82: def wrap_in template
83: clone.wrap_in! template
84: end
# File lib/coderay/encoders/html/output.rb, line 86
86: def wrap_in! template
87: Template.wrap! self, template, 'CONTENT'
88: self
89: end
# File lib/coderay/encoders/html/output.rb, line 77
77: def wrapped_in
78: @wrapped_in ||= nil
79: end