Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup HTML::Output #140

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 6 additions & 4 deletions lib/coderay/encoders/html.rb
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,11 @@ def finish options
end

if @out.respond_to? :to_str
@out.extend Output
@out.css = @css
if options[:line_numbers]
Numbering.number! @out, options[:line_numbers], options
end
@out.wrap! options[:wrap]
@out.apply_title! options[:title]
@out = Output.wrap_string_in @out, options[:wrap], @css if options[:wrap]
@out = @out.sub(/(<title>)(<\/title>)/) { $1 + options[:title] + $2 } if options[:title]
end

if defined?(@real_out) && @real_out
Expand Down Expand Up @@ -274,6 +272,10 @@ def check_options! options
raise ArgumentError, 'Unknown value %p for :css.' % [options[:css]]
end

unless [nil, false, :span, :div, :page].include? options[:wrap]
raise ArgumentError, 'Unknown value %p for :wrap.' % [options[:wrap]]
end

options[:break_lines] = true if options[:line_numbers] == :inline
end

Expand Down
26 changes: 11 additions & 15 deletions lib/coderay/encoders/html/numbering.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
module CodeRay
module Encoders

class HTML

module Numbering # :nodoc:

def self.number! output, mode = :table, options = {}
return self unless mode

options = DEFAULT_OPTIONS.merge options

start = options[:line_number_start]
unless start.is_a? Integer
raise ArgumentError, "Invalid value %p for :line_number_start; Integer expected." % start
raise ArgumentError, "Invalid value %p for :line_number_start; Integer expected." % [start]
end

anchor_prefix = options[:line_number_anchors]
Expand Down Expand Up @@ -53,7 +50,7 @@ def self.number! output, mode = :table, options = {}
end
end
else
raise ArgumentError, 'Invalid value %p for :bolding; false or Integer expected.' % bold_every
raise ArgumentError, 'Invalid value %p for :bolding; false or Integer expected.' % [bold_every]
end

if position_of_last_newline = output.rindex(RUBY_VERSION >= '1.9' ? /\n/ : ?\n)
Expand Down Expand Up @@ -83,26 +80,25 @@ def self.number! output, mode = :table, options = {}
when :table
line_numbers = (start ... start + line_count).map(&bolding).join("\n")
line_numbers << "\n"
line_numbers_table_template = Output::TABLE.apply('LINE_NUMBERS', line_numbers)
line_numbers_table_template = TABLE.sub('<%LINE_NUMBERS%>', line_numbers)

output.gsub!(/<\/div>\n/, '</div>')
output.wrap_in! line_numbers_table_template
output.wrapped_in = :div

when :list
raise NotImplementedError, 'The :list option is no longer available. Use :table.'
output.replace line_numbers_table_template.sub('<%CONTENT%>', output)

else
raise ArgumentError, 'Unknown value %p for mode: expected one of %p' %
[mode, [:table, :inline]]
raise ArgumentError, 'Unknown value %p for mode: expected one of %p' % [mode, [:table, :inline]]
end

output
end

TABLE = <<-TABLE
<table class="CodeRay"><tr>
<td class="line-numbers"><pre><%LINE_NUMBERS%></pre></td>
<td class="code"><pre><%CONTENT%></pre></td>
</tr></table>
TABLE
end

end

end
end
143 changes: 23 additions & 120 deletions lib/coderay/encoders/html/output.rb
Original file line number Diff line number Diff line change
@@ -1,135 +1,41 @@
module CodeRay
module Encoders

class HTML

# This module is included in the output String of the HTML Encoder.
#
# It provides methods like wrap, div, page etc.
#
# Remember to use #clone instead of #dup to keep the modules the object was
# extended with.
#
# TODO: Rewrite this without monkey patching.
module Output

attr_accessor :css

class << self

# 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.
def extended o # :nodoc:
warn "The Output module is intended to extend instances of String, not #{o.class}." unless o.respond_to? :to_str
end

def make_stylesheet css, in_tag = false # :nodoc:
sheet = css.stylesheet
sheet = <<-'CSS' if in_tag
<style type="text/css">
#{sheet}
</style>
CSS
sheet
end

def page_template_for_css css # :nodoc:
sheet = make_stylesheet css
PAGE.apply 'CSS', sheet
end

end

def wrapped_in? element
wrapped_in == element
end

def wrapped_in
@wrapped_in ||= nil
end
attr_writer :wrapped_in

def wrap_in! template
Template.wrap! self, template, 'CONTENT'
self
end

def apply_title! title
self.sub!(/(<title>)(<\/title>)/) { $1 + title + $2 }
self
end

def wrap! element, *args
return self if not element or element == wrapped_in
def self.wrap_string_in string, element, css = nil
case element
when :div
raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? nil
wrap_in! DIV
when :span
raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? nil
wrap_in! SPAN
SPAN
when :div
return string if string[/\A<(?:div|table)\b/]
DIV
when :page
wrap! :div if wrapped_in? nil
raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? :div
wrap_in! Output.page_template_for_css(@css)
if args.first.is_a?(Hash) && title = args.first[:title]
apply_title! title
end
self
when nil
return self
string = wrap_string_in(string, :div) unless string[/\A<(?:div|table)\b/]
PAGE.sub('<%CSS%>', css ? css.stylesheet : '')
else
raise "Unknown value %p for :wrap" % element
end
@wrapped_in = element
self
end

def stylesheet in_tag = false
Output.make_stylesheet @css, in_tag
raise ArgumentError, 'Unknown wrap element: %p' % [element]
end.sub('<%CONTENT%>', string)
end

#-- don't include the templates in docu

class Template < String # :nodoc:

def self.wrap! str, template, target
target = Regexp.new(Regexp.escape("<%#{target}%>"))
if template =~ target
str[0,0] = $`
str << $'
else
raise "Template target <%%%p%%> not found" % target
end
end

def apply target, replacement
target = Regexp.new(Regexp.escape("<%#{target}%>"))
if self =~ target
Template.new($` + replacement + $')
else
raise "Template target <%%%p%%> not found" % target
end

def self.wrap! str, template, target
target = Regexp.new(Regexp.escape("<%#{target}%>"))
if template =~ target
str[0,0] = $`
str << $'
else
raise "Template target <%%%p%%> not found" % target
end

end

SPAN = Template.new '<span class="CodeRay"><%CONTENT%></span>'

DIV = Template.new <<-DIV
SPAN = '<span class="CodeRay"><%CONTENT%></span>'
DIV = <<-DIV
<div class="CodeRay">
<div class="code"><pre><%CONTENT%></pre></div>
</div>
DIV

TABLE = Template.new <<-TABLE
<table class="CodeRay"><tr>
<td class="line-numbers"><pre><%LINE_NUMBERS%></pre></td>
<td class="code"><pre><%CONTENT%></pre></td>
</tr></table>
TABLE

PAGE = Template.new <<-PAGE

PAGE = <<-PAGE
<!DOCTYPE html>
<html>
<head>
Expand Down Expand Up @@ -157,10 +63,7 @@ def apply target, replacement
</body>
</html>
PAGE

end

end

end
end