Chris@909
|
1 module CodeRay
|
Chris@909
|
2 module Encoders
|
Chris@909
|
3
|
Chris@909
|
4 class HTML
|
Chris@909
|
5
|
Chris@909
|
6 # This module is included in the output String of the HTML Encoder.
|
Chris@909
|
7 #
|
Chris@909
|
8 # It provides methods like wrap, div, page etc.
|
Chris@909
|
9 #
|
Chris@909
|
10 # Remember to use #clone instead of #dup to keep the modules the object was
|
Chris@909
|
11 # extended with.
|
Chris@909
|
12 #
|
Chris@909
|
13 # TODO: Rewrite this without monkey patching.
|
Chris@909
|
14 module Output
|
Chris@909
|
15
|
Chris@909
|
16 attr_accessor :css
|
Chris@909
|
17
|
Chris@909
|
18 class << self
|
Chris@909
|
19
|
Chris@909
|
20 # Raises an exception if an object that doesn't respond to to_str is extended by Output,
|
Chris@909
|
21 # to prevent users from misuse. Use Module#remove_method to disable.
|
Chris@909
|
22 def extended o # :nodoc:
|
Chris@909
|
23 warn "The Output module is intended to extend instances of String, not #{o.class}." unless o.respond_to? :to_str
|
Chris@909
|
24 end
|
Chris@909
|
25
|
Chris@909
|
26 def make_stylesheet css, in_tag = false # :nodoc:
|
Chris@909
|
27 sheet = css.stylesheet
|
Chris@909
|
28 sheet = <<-'CSS' if in_tag
|
Chris@909
|
29 <style type="text/css">
|
Chris@909
|
30 #{sheet}
|
Chris@909
|
31 </style>
|
Chris@909
|
32 CSS
|
Chris@909
|
33 sheet
|
Chris@909
|
34 end
|
Chris@909
|
35
|
Chris@909
|
36 def page_template_for_css css # :nodoc:
|
Chris@909
|
37 sheet = make_stylesheet css
|
Chris@909
|
38 PAGE.apply 'CSS', sheet
|
Chris@909
|
39 end
|
Chris@909
|
40
|
Chris@909
|
41 end
|
Chris@909
|
42
|
Chris@909
|
43 def wrapped_in? element
|
Chris@909
|
44 wrapped_in == element
|
Chris@909
|
45 end
|
Chris@909
|
46
|
Chris@909
|
47 def wrapped_in
|
Chris@909
|
48 @wrapped_in ||= nil
|
Chris@909
|
49 end
|
Chris@909
|
50 attr_writer :wrapped_in
|
Chris@909
|
51
|
Chris@909
|
52 def wrap_in! template
|
Chris@909
|
53 Template.wrap! self, template, 'CONTENT'
|
Chris@909
|
54 self
|
Chris@909
|
55 end
|
Chris@909
|
56
|
Chris@909
|
57 def apply_title! title
|
Chris@909
|
58 self.sub!(/(<title>)(<\/title>)/) { $1 + title + $2 }
|
Chris@909
|
59 self
|
Chris@909
|
60 end
|
Chris@909
|
61
|
Chris@909
|
62 def wrap! element, *args
|
Chris@909
|
63 return self if not element or element == wrapped_in
|
Chris@909
|
64 case element
|
Chris@909
|
65 when :div
|
Chris@909
|
66 raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? nil
|
Chris@909
|
67 wrap_in! DIV
|
Chris@909
|
68 when :span
|
Chris@909
|
69 raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? nil
|
Chris@909
|
70 wrap_in! SPAN
|
Chris@909
|
71 when :page
|
Chris@909
|
72 wrap! :div if wrapped_in? nil
|
Chris@909
|
73 raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? :div
|
Chris@909
|
74 wrap_in! Output.page_template_for_css(@css)
|
Chris@909
|
75 if args.first.is_a?(Hash) && title = args.first[:title]
|
Chris@909
|
76 apply_title! title
|
Chris@909
|
77 end
|
Chris@909
|
78 self
|
Chris@909
|
79 when nil
|
Chris@909
|
80 return self
|
Chris@909
|
81 else
|
Chris@909
|
82 raise "Unknown value %p for :wrap" % element
|
Chris@909
|
83 end
|
Chris@909
|
84 @wrapped_in = element
|
Chris@909
|
85 self
|
Chris@909
|
86 end
|
Chris@909
|
87
|
Chris@909
|
88 def stylesheet in_tag = false
|
Chris@909
|
89 Output.make_stylesheet @css, in_tag
|
Chris@909
|
90 end
|
Chris@909
|
91
|
Chris@909
|
92 #-- don't include the templates in docu
|
Chris@909
|
93
|
Chris@909
|
94 class Template < String # :nodoc:
|
Chris@909
|
95
|
Chris@909
|
96 def self.wrap! str, template, target
|
Chris@909
|
97 target = Regexp.new(Regexp.escape("<%#{target}%>"))
|
Chris@909
|
98 if template =~ target
|
Chris@909
|
99 str[0,0] = $`
|
Chris@909
|
100 str << $'
|
Chris@909
|
101 else
|
Chris@909
|
102 raise "Template target <%%%p%%> not found" % target
|
Chris@909
|
103 end
|
Chris@909
|
104 end
|
Chris@909
|
105
|
Chris@909
|
106 def apply target, replacement
|
Chris@909
|
107 target = Regexp.new(Regexp.escape("<%#{target}%>"))
|
Chris@909
|
108 if self =~ target
|
Chris@909
|
109 Template.new($` + replacement + $')
|
Chris@909
|
110 else
|
Chris@909
|
111 raise "Template target <%%%p%%> not found" % target
|
Chris@909
|
112 end
|
Chris@909
|
113 end
|
Chris@909
|
114
|
Chris@909
|
115 end
|
Chris@909
|
116
|
Chris@909
|
117 SPAN = Template.new '<span class="CodeRay"><%CONTENT%></span>'
|
Chris@909
|
118
|
Chris@909
|
119 DIV = Template.new <<-DIV
|
Chris@909
|
120 <div class="CodeRay">
|
Chris@909
|
121 <div class="code"><pre><%CONTENT%></pre></div>
|
Chris@909
|
122 </div>
|
Chris@909
|
123 DIV
|
Chris@909
|
124
|
Chris@909
|
125 TABLE = Template.new <<-TABLE
|
Chris@909
|
126 <table class="CodeRay"><tr>
|
Chris@909
|
127 <td class="line-numbers" title="double click to toggle" ondblclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre><%LINE_NUMBERS%></pre></td>
|
Chris@909
|
128 <td class="code"><pre><%CONTENT%></pre></td>
|
Chris@909
|
129 </tr></table>
|
Chris@909
|
130 TABLE
|
Chris@909
|
131
|
Chris@909
|
132 PAGE = Template.new <<-PAGE
|
Chris@909
|
133 <!DOCTYPE html>
|
Chris@909
|
134 <html>
|
Chris@909
|
135 <head>
|
Chris@909
|
136 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
Chris@909
|
137 <title></title>
|
Chris@909
|
138 <style type="text/css">
|
Chris@909
|
139 .CodeRay .line-numbers a {
|
Chris@909
|
140 text-decoration: inherit;
|
Chris@909
|
141 color: inherit;
|
Chris@909
|
142 }
|
Chris@909
|
143 <%CSS%>
|
Chris@909
|
144 </style>
|
Chris@909
|
145 </head>
|
Chris@909
|
146 <body style="background-color: white;">
|
Chris@909
|
147
|
Chris@909
|
148 <%CONTENT%>
|
Chris@909
|
149 </body>
|
Chris@909
|
150 </html>
|
Chris@909
|
151 PAGE
|
Chris@909
|
152
|
Chris@909
|
153 end
|
Chris@909
|
154
|
Chris@909
|
155 end
|
Chris@909
|
156
|
Chris@909
|
157 end
|
Chris@909
|
158 end
|