erbook 6.1.0 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/erbook +29 -25
- data/doc/HelloWorld.spec +3 -1
- data/doc/api/classes/ERBook.html +86 -0
- data/doc/api/classes/ERBook/Document.html +399 -0
- data/doc/api/classes/ERBook/Document/Node.html +110 -0
- data/doc/api/classes/ERBook/Template.html +309 -0
- data/doc/api/classes/ERBook/Template/Sandbox.html +134 -0
- data/doc/api/classes/RDoc.html +69 -0
- data/doc/api/classes/RDoc/AnyMethod.html +249 -0
- data/doc/api/classes/RDoc/DummyMarkup.html +60 -0
- data/doc/api/classes/RDoc/DummyMixin.html +54 -0
- data/doc/api/classes/RDoc/DummyOptions.html +60 -0
- data/doc/api/classes/RDoc/TopLevel.html +344 -0
- data/doc/api/classes/String.html +212 -0
- data/doc/api/created.rid +1 -0
- data/doc/api/css/main.css +263 -0
- data/doc/api/css/panel.css +383 -0
- data/doc/api/css/reset.css +53 -0
- data/doc/api/files/ANN_eml.html +276 -0
- data/doc/api/files/ANN_html.html +407 -0
- data/doc/api/files/ANN_txt.html +271 -0
- data/doc/api/files/LICENSE.html +76 -0
- data/doc/api/files/lib/erbook/document_rb.html +74 -0
- data/doc/api/files/lib/erbook/rdoc_rb.html +77 -0
- data/doc/api/files/lib/erbook/template_rb.html +66 -0
- data/doc/api/files/lib/erbook/to_xhtml_rb.html +89 -0
- data/doc/api/files/lib/erbook_rb.html +70 -0
- data/doc/api/i/arrows.png +0 -0
- data/doc/api/i/results_bg.png +0 -0
- data/doc/api/i/tree_bg.png +0 -0
- data/doc/api/index.html +14 -18
- data/doc/api/js/jquery-1.3.2.min.js +19 -0
- data/doc/api/js/jquery-effect.js +593 -0
- data/doc/api/js/main.js +22 -0
- data/doc/api/js/searchdoc.js +605 -0
- data/doc/api/panel/index.html +63 -0
- data/doc/api/panel/search_index.js +1 -0
- data/doc/api/panel/tree.js +1 -0
- data/doc/formats.erb +63 -115
- data/doc/history.erb +125 -92
- data/doc/index.erb +12 -7
- data/doc/index.xhtml +1020 -1347
- data/doc/intro.erb +42 -40
- data/doc/setup.erb +18 -18
- data/doc/theory.erb +24 -31
- data/doc/usage.erb +14 -24
- data/fmt/xhtml.icons/index.yaml +16 -14
- data/fmt/xhtml.icons/rakefile +33 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/16x16/places/start-here.png +0 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/32x32/actions/go-down.png +0 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/32x32/actions/go-up.png +0 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/32x32/places/start-here.png +0 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/32x32/status/software-update-available.png +0 -0
- data/fmt/xhtml.icons/{tango-icon-theme-0.8.1 → tango-icon-theme-0.8.90}/48x48/apps/accessories-text-editor.png +0 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/48x48/apps/internet-group-chat.png +0 -0
- data/fmt/xhtml.icons/{tango-icon-theme-0.8.1 → tango-icon-theme-0.8.90}/48x48/emblems/emblem-important.png +0 -0
- data/fmt/xhtml.icons/{tango-icon-theme-0.8.1 → tango-icon-theme-0.8.90}/48x48/status/dialog-error.png +0 -0
- data/fmt/xhtml.icons/{tango-icon-theme-0.8.1 → tango-icon-theme-0.8.90}/48x48/status/dialog-information.png +0 -0
- data/fmt/xhtml.icons/{tango-icon-theme-0.8.1 → tango-icon-theme-0.8.90}/48x48/status/dialog-warning.png +0 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/COPYING +1 -0
- data/fmt/xhtml.icons/{tango-icon-theme-0.8.1 → tango-icon-theme-0.8.90}/README +0 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/actions/bookmark-new.svg +672 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/actions/go-down.svg +200 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/actions/go-home.svg +445 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/actions/go-up.svg +196 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/actions/view-refresh.svg +393 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/apps/accessories-text-editor.svg +554 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/apps/internet-group-chat.svg +312 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/emblems/emblem-favorite.svg +242 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/emblems/emblem-important.svg +164 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/mimetypes/application-certificate.svg +443 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/places/start-here.svg +492 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/status/dialog-error.svg +330 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/status/dialog-information.svg +1159 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/status/dialog-warning.svg +373 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.90/scalable/status/software-update-available.svg +209 -0
- data/fmt/xhtml.scripts/jquery-1.3.2.min.js +19 -0
- data/fmt/xhtml.scripts/jquery.localscroll-1.2.7-min.js +9 -0
- data/fmt/xhtml.scripts/jquery.scrollTo-1.4.1-min.js +11 -0
- data/fmt/xhtml.yaml +470 -454
- data/lang/de.yaml +5 -5
- data/lang/el.yaml +4 -4
- data/lang/es.yaml +5 -5
- data/lang/fr.yaml +5 -5
- data/lang/it.yaml +5 -5
- data/lang/ja.yaml +4 -4
- data/lang/ko.yaml +4 -4
- data/lang/nl.yaml +4 -4
- data/lang/phrases.yaml +4 -4
- data/lang/pt.yaml +5 -5
- data/lang/ru.yaml +5 -5
- data/lang/zh.yaml +5 -5
- data/lang/zt.yaml +5 -5
- data/lib/erbook.rb +12 -5
- data/lib/erbook/document.rb +127 -107
- data/lib/erbook/rdoc.rb +18 -11
- data/lib/erbook/template.rb +86 -176
- data/lib/erbook/to_xhtml.rb +98 -25
- data/{Rakefile → rakefile} +1 -0
- metadata +106 -53
- data/doc/api/ERBook.html +0 -35
- data/doc/api/ERBook/Document.html +0 -669
- data/doc/api/ERBook/Document/Node.html +0 -102
- data/doc/api/ERBook/Template.html +0 -670
- data/doc/api/RDoc.html +0 -23
- data/doc/api/RDoc/AnyMethod.html +0 -302
- data/doc/api/RDoc/DummyMarkup.html +0 -73
- data/doc/api/RDoc/DummyMixin.html +0 -23
- data/doc/api/RDoc/DummyOptions.html +0 -140
- data/doc/api/RDoc/TopLevel.html +0 -465
- data/doc/api/String.html +0 -372
- data/doc/api/all-methods.html +0 -253
- data/doc/api/all-namespaces.html +0 -42
- data/doc/api/app.js +0 -18
- data/doc/api/jquery.js +0 -11
- data/doc/api/readme.html +0 -38
- data/doc/api/style.css +0 -68
- data/doc/api/syntax_highlight.css +0 -21
- data/fmt/xhtml.icons/tango-icon-theme-0.8.1/48x48/README +0 -2
- data/fmt/xhtml.icons/tango-icon-theme-0.8.1/48x48/apps/internet-group-chat.png +0 -0
- data/fmt/xhtml.icons/tango-icon-theme-0.8.1/COPYING +0 -67
data/lib/erbook/rdoc.rb
CHANGED
@@ -1,17 +1,23 @@
|
|
1
|
-
# Workaround for
|
2
|
-
|
1
|
+
# Workaround for `rdoc --fmt xml` not dumping information about methods.
|
2
|
+
#--
|
3
|
+
# Copyright 2008 Suraj N. Kurapati
|
4
|
+
# See the LICENSE file for details.
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
gem 'rdoc', '>= 2.4.3', '< 2.5'
|
3
9
|
require 'rdoc/rdoc'
|
4
10
|
|
5
11
|
module RDoc
|
6
12
|
class TopLevel
|
7
13
|
# Returns an array of all classes recorded thus far.
|
8
14
|
def self.all_classes
|
9
|
-
|
15
|
+
@all_classes.values
|
10
16
|
end
|
11
17
|
|
12
18
|
# Returns an array of all modules recorded thus far.
|
13
19
|
def self.all_modules
|
14
|
-
|
20
|
+
@all_modules.values
|
15
21
|
end
|
16
22
|
|
17
23
|
# Returns an array of RDoc::AnyMethod objects
|
@@ -25,10 +31,10 @@ module RDoc
|
|
25
31
|
def self.refresh_all_classes_and_modules
|
26
32
|
visit = lambda do |node|
|
27
33
|
if node.is_a? NormalClass or node.is_a? SingleClass
|
28
|
-
|
34
|
+
@all_classes[node.full_name] = node
|
29
35
|
|
30
36
|
elsif node.is_a? NormalModule
|
31
|
-
|
37
|
+
@all_modules[node.full_name] = node
|
32
38
|
end
|
33
39
|
|
34
40
|
(node.classes + node.modules).each {|n| visit[n] }
|
@@ -48,14 +54,15 @@ module RDoc
|
|
48
54
|
# RDoc will ignore the given code string! :-(
|
49
55
|
#
|
50
56
|
def self.parse aCodeString, aFileName = __FILE__
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
57
|
+
tl = TopLevel.new(aFileName)
|
58
|
+
op = DummyOptions.new
|
59
|
+
st = Stats.new(0)
|
60
|
+
|
61
|
+
result = Parser.for(tl, aFileName, aCodeString, op, st).scan
|
55
62
|
|
56
63
|
refresh_all_classes_and_modules
|
57
64
|
|
58
|
-
|
65
|
+
result
|
59
66
|
end
|
60
67
|
|
61
68
|
# Returns a RDoc::TopLevel object containing information
|
data/lib/erbook/template.rb
CHANGED
@@ -1,210 +1,120 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
#--
|
2
|
+
# Copyright 2008 Suraj N. Kurapati
|
3
|
+
# See the LICENSE file for details.
|
4
|
+
#++
|
5
|
+
|
6
|
+
require 'ember'
|
3
7
|
|
4
8
|
module ERBook
|
5
9
|
##
|
6
|
-
#
|
10
|
+
# eRuby template that provides access to the underlying result
|
7
11
|
# buffer (which contains the result of template evaluation thus
|
8
12
|
# far) and provides sandboxing for isolated template rendering.
|
9
13
|
#
|
10
|
-
|
11
|
-
|
12
|
-
# * Lines that begin with '%' are treated as normal eRuby directives.
|
13
|
-
#
|
14
|
-
# * Include directives (<%#include YOUR_PATH #%>) are replaced by the result
|
15
|
-
# of reading and evaluating the YOUR_PATH file in the current context.
|
16
|
-
#
|
17
|
-
# * Unless YOUR_PATH is an absolute path, it is treated as being
|
18
|
-
# relative to the file which contains the include directive.
|
19
|
-
#
|
20
|
-
# * Errors originating from included files are given a proper
|
21
|
-
# stack trace which shows the chain of inclusion plus any
|
22
|
-
# further trace steps originating from the included file itself.
|
23
|
-
#
|
24
|
-
# * eRuby directives delimiting Ruby blocks (<% ... do %>
|
25
|
-
# ... <% end %>) can be heirarchically unindented by the
|
26
|
-
# crown margin of the opening (<% ... do %>) delimiter.
|
27
|
-
#
|
28
|
-
class Template < ERB
|
29
|
-
# The result of template evaluation thus far.
|
30
|
-
attr_reader :buffer
|
14
|
+
class Template < Ember::Template
|
15
|
+
attr_reader :sandbox
|
31
16
|
|
32
17
|
##
|
33
|
-
#
|
18
|
+
# ==== Parameters
|
19
|
+
#
|
20
|
+
# [source]
|
34
21
|
# Replacement for the ambiguous '(erb)' identifier in stack traces;
|
35
22
|
# so that the user can better determine the source of an error.
|
36
23
|
#
|
37
|
-
#
|
24
|
+
# [input]
|
38
25
|
# A string containing eRuby directives.
|
39
26
|
#
|
40
|
-
#
|
27
|
+
# [unindent]
|
41
28
|
# If true, then all content blocks will be unindented hierarchically,
|
42
|
-
# by the leading space of their 'do' and 'end' delimiters.
|
43
29
|
#
|
44
|
-
#
|
30
|
+
# [safe_level]
|
45
31
|
# See safe_level in ERB::new().
|
46
32
|
#
|
47
|
-
def initialize source, input, unindent =
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
else
|
63
|
-
# resolve correct path of target file
|
64
|
-
dst_file = chunk
|
65
|
-
|
66
|
-
unless Pathname.new(dst_file).absolute?
|
67
|
-
# target is relative to the file in
|
68
|
-
# which the include directive exists
|
69
|
-
dst_file = File.join(File.dirname(src_file), dst_file)
|
70
|
-
end
|
71
|
-
|
72
|
-
dst_path = File.expand_path(dst_file)
|
73
|
-
|
74
|
-
# include the target file
|
75
|
-
if path_stack.include? dst_file
|
76
|
-
raise "Cannot include #{dst_file.inspect} at #{src_file.inspect}:#{src_line} because that would cause an infinite loop in the inclusion stack: #{path_stack.inspect}."
|
77
|
-
else
|
78
|
-
stack_trace.push "#{src_path}:#{src_line}"
|
79
|
-
dst_text = eval('File.read dst_file', binding, src_file, src_line)
|
80
|
-
|
81
|
-
# recursively expand any include directives within
|
82
|
-
# the expansion of the current include directive
|
83
|
-
dst_text = expander[dst_file, dst_text, path_stack, stack_trace]
|
84
|
-
|
85
|
-
# provide more accurate stack trace for
|
86
|
-
# errors originating from included files
|
87
|
-
line_var = "__erbook_var_#{dst_file.object_id.abs}__"
|
88
|
-
dst_text = %{<%
|
89
|
-
#{line_var} = __LINE__ + 2 # content is 2 newlines below
|
90
|
-
begin
|
91
|
-
%>#{dst_text}<%
|
92
|
-
rescue Exception => err
|
93
|
-
bak = err.backtrace
|
94
|
-
|
95
|
-
top = []
|
96
|
-
found_top = false
|
97
|
-
prev_line = nil
|
98
|
-
|
99
|
-
bak.each do |step|
|
100
|
-
if step =~ /^#{/#{source}/}:(\\d+)(.*)/
|
101
|
-
line, desc = $1, $2
|
102
|
-
line = line.to_i - #{line_var} + 1
|
103
|
-
|
104
|
-
if line > 0 and line != prev_line
|
105
|
-
top << "#{dst_path}:\#{line}\#{desc}"
|
106
|
-
found_top = true
|
107
|
-
prev_line = line
|
108
|
-
end
|
109
|
-
elsif !found_top
|
110
|
-
top << step
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
if found_top
|
115
|
-
bak.replace top
|
116
|
-
bak.concat #{stack_trace.reverse.inspect}
|
117
|
-
end
|
118
|
-
|
119
|
-
raise err
|
120
|
-
end
|
121
|
-
%>}
|
122
|
-
|
123
|
-
stack_trace.pop
|
124
|
-
end
|
125
|
-
|
126
|
-
chunks[i] = dst_text
|
127
|
-
end
|
128
|
-
end
|
129
|
-
path_stack.pop
|
130
|
-
|
131
|
-
chunks.join
|
132
|
-
end
|
133
|
-
|
134
|
-
input = expander[source, input, [], []]
|
135
|
-
|
136
|
-
# convert "% at beginning of line" usage into <% normal %> usage
|
137
|
-
input.gsub! %r{^([ \t]*)(%[=# \t].*)$}, '\1<\2 %>'
|
138
|
-
input.gsub! %r{^([ \t]*)%%}, '\1%'
|
139
|
-
|
140
|
-
# unindent node content hierarchically
|
141
|
-
if unindent
|
142
|
-
tags = input.scan(/<%(?:.(?!<%))*?%>/m)
|
143
|
-
margins = []
|
144
|
-
result = []
|
145
|
-
|
146
|
-
buffer = input
|
147
|
-
tags.each do |tag|
|
148
|
-
chunk, buffer = buffer.split(tag, 2)
|
149
|
-
chunk << tag
|
150
|
-
|
151
|
-
# perform unindentation
|
152
|
-
result << chunk.gsub(/^#{margins.last}/, '')
|
153
|
-
|
154
|
-
# prepare for next unindentation
|
155
|
-
case tag
|
156
|
-
when /<%[^%=].*?\bdo\b.*?%>/m
|
157
|
-
margins.push buffer[/^[ \t]*(?=\S)/]
|
158
|
-
|
159
|
-
when /<%\s*end\s*%>/m
|
160
|
-
margins.pop
|
161
|
-
end
|
162
|
-
end
|
163
|
-
result << buffer
|
164
|
-
|
165
|
-
input = result.join
|
33
|
+
def initialize source, input, unindent = true, safe_level = nil
|
34
|
+
super input,
|
35
|
+
:result_variable => :@buffer,
|
36
|
+
:source_file => source,
|
37
|
+
:unindent => unindent,
|
38
|
+
:shorthand => true,
|
39
|
+
:infer_end => true
|
40
|
+
|
41
|
+
@sandbox = Sandbox.new
|
42
|
+
|
43
|
+
if $DEBUG
|
44
|
+
IO.popen('cat -n', 'w+') do |io|
|
45
|
+
io.write self.program
|
46
|
+
io.close_write
|
47
|
+
STDERR.puts io.read
|
166
48
|
end
|
49
|
+
end
|
50
|
+
end
|
167
51
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
52
|
+
##
|
53
|
+
# Returns the output of evaluating this template inside the given context.
|
54
|
+
#
|
55
|
+
# If no context is given, then the sandbox of this template is used.
|
56
|
+
#
|
57
|
+
def render
|
58
|
+
super @sandbox.instance_eval('binding')
|
59
|
+
end
|
173
60
|
|
174
|
-
|
61
|
+
##
|
62
|
+
# Returns the result of template evaluation thus far.
|
63
|
+
#
|
64
|
+
def buffer
|
65
|
+
@sandbox.instance_variable_get(:@buffer)
|
175
66
|
end
|
176
67
|
|
177
|
-
|
68
|
+
##
|
69
|
+
# Renders this template within a fresh sandbox that is populated with
|
178
70
|
# the given instance variables, whose names must be prefixed with '@'.
|
71
|
+
#
|
179
72
|
def render_with inst_vars = {}
|
180
|
-
|
73
|
+
old_sandbox = @sandbox
|
74
|
+
|
75
|
+
begin
|
76
|
+
@sandbox = Sandbox.new
|
77
|
+
|
181
78
|
inst_vars.each_pair do |var, val|
|
182
|
-
instance_variable_set var, val
|
79
|
+
@sandbox.instance_variable_set var, val
|
183
80
|
end
|
184
81
|
|
185
|
-
|
186
|
-
end
|
82
|
+
render
|
187
83
|
|
188
|
-
|
84
|
+
ensure
|
85
|
+
@sandbox = old_sandbox
|
86
|
+
end
|
189
87
|
end
|
190
88
|
|
191
|
-
|
192
|
-
|
193
|
-
#
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
89
|
+
##
|
90
|
+
# Environment for template evaluation.
|
91
|
+
#
|
92
|
+
class Sandbox
|
93
|
+
##
|
94
|
+
# Returns an array of things that the given
|
95
|
+
# block wants to append to the buffer. If
|
96
|
+
# the given block does not want to append
|
97
|
+
# to the buffer, then returns the result of
|
98
|
+
# invoking the given block inside an array.
|
99
|
+
#
|
100
|
+
def __block_content__ *block_args
|
101
|
+
raise ArgumentError, 'block must be given' unless block_given?
|
102
|
+
|
103
|
+
original = @buffer
|
104
|
+
|
105
|
+
begin
|
106
|
+
block_content = @buffer = []
|
107
|
+
return_value = yield(*block_args) # this appends content to @buffer
|
108
|
+
ensure
|
109
|
+
@buffer = original
|
110
|
+
end
|
202
111
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
112
|
+
if block_content.empty?
|
113
|
+
[return_value]
|
114
|
+
else
|
115
|
+
block_content
|
116
|
+
end
|
117
|
+
end
|
208
118
|
end
|
209
119
|
end
|
210
120
|
end
|
data/lib/erbook/to_xhtml.rb
CHANGED
@@ -4,13 +4,18 @@
|
|
4
4
|
# This particular implementation features the Markdown
|
5
5
|
# formatting system via Maruku, syntax coloring via CodeRay,
|
6
6
|
# and smart source code sizing (block versus inline display).
|
7
|
+
#--
|
8
|
+
# Copyright 2006 Suraj N. Kurapati
|
9
|
+
# See the LICENSE file for details.
|
10
|
+
#++
|
7
11
|
|
8
12
|
require 'cgi'
|
13
|
+
require 'digest/sha1'
|
9
14
|
|
10
15
|
begin
|
11
16
|
require 'rubygems'
|
12
17
|
gem 'maruku', '~> 0.5'
|
13
|
-
gem 'coderay', '>= 0.
|
18
|
+
gem 'coderay', '>= 0.8'
|
14
19
|
rescue LoadError
|
15
20
|
end
|
16
21
|
|
@@ -22,23 +27,33 @@ class String
|
|
22
27
|
# they are being processed by Textile. By doing this, we
|
23
28
|
# avoid unwanted Textile transformations, such as quotation
|
24
29
|
# marks becoming curly ( ), in source code.
|
25
|
-
PROTECTED_TAGS =
|
30
|
+
PROTECTED_TAGS = {
|
31
|
+
:pre => :block, # tag => is it a block or inline element?
|
32
|
+
:code => :inline,
|
33
|
+
:tt => :inline
|
34
|
+
}
|
26
35
|
|
27
36
|
# The content of these XHTML tags will be preserved
|
28
37
|
# *verbatim* throughout the text-to-XHTML conversion process.
|
29
|
-
VERBATIM_TAGS =
|
38
|
+
VERBATIM_TAGS = {
|
39
|
+
:noformat => :block # tag => is it a block or inline element?
|
40
|
+
}
|
30
41
|
|
42
|
+
##
|
31
43
|
# Transforms this string into an *inline* XHTML string (one that
|
32
44
|
# does not contain any block-level XHTML elements at the root).
|
45
|
+
#
|
33
46
|
def to_inline_xhtml
|
34
47
|
to_xhtml true
|
35
48
|
end
|
36
49
|
|
50
|
+
##
|
37
51
|
# Transforms this string into XHTML while ensuring that the
|
38
52
|
# result contains one or more block-level elements at the root.
|
39
53
|
#
|
40
|
-
# inline
|
41
|
-
#
|
54
|
+
# [inline]
|
55
|
+
# If true, the resulting XHTML will *not*
|
56
|
+
# contain a block-level element at the root.
|
42
57
|
#
|
43
58
|
def to_xhtml inline = false
|
44
59
|
with_protected_tags(self, VERBATIM_TAGS, true) do |text|
|
@@ -63,51 +78,85 @@ class String
|
|
63
78
|
end
|
64
79
|
end
|
65
80
|
|
81
|
+
##
|
66
82
|
# Returns the result of running this string through Maruku.
|
67
83
|
#
|
68
|
-
# inline
|
69
|
-
#
|
84
|
+
# [inline]
|
85
|
+
# If true, the resulting XHTML will *not*
|
86
|
+
# be wrapped in a XHTML paragraph element.
|
70
87
|
#
|
71
88
|
def thru_maruku inline = false #:nodoc:
|
72
|
-
|
89
|
+
#
|
90
|
+
# XXX: add a newline at the beginning of the text to
|
91
|
+
# prevent Maruku from interpreting the first line
|
92
|
+
# of text as a parameter definition, which is the
|
93
|
+
# case if that first line matches /\S{2}: /
|
94
|
+
#
|
95
|
+
# see this bug report for details:
|
96
|
+
# http://rubyforge.org/tracker/?func=detail&atid=10735&aid=25697&group_id=2795
|
97
|
+
#
|
98
|
+
html = Maruku.new("\n#{self}").to_html
|
73
99
|
html.sub! %r{\A<p>(.*)</p>\Z}, '\1' if inline
|
74
100
|
html
|
75
101
|
end
|
76
102
|
|
77
|
-
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
103
|
+
##
|
104
|
+
# Adds syntax coloring to <code> elements in this string.
|
105
|
+
#
|
106
|
+
# Each <code> element is annotated with a class="line"
|
107
|
+
# or a class="para" attribute, according to whether it
|
108
|
+
# spans a single line or multiple lines of code.
|
109
|
+
#
|
110
|
+
# In the latter case, the <code> element is replaced with a <pre> element
|
111
|
+
# so that its multi-line body appears correctly in text-mode web browsers.
|
112
|
+
#
|
113
|
+
# If a <code> element has a lang="..." attribute,
|
114
|
+
# then that attribute's value is considered to be
|
115
|
+
# the programming language for which appropriate
|
116
|
+
# syntax coloring should be applied. Otherwise,
|
117
|
+
# the programming language is assumed to be ruby.
|
118
|
+
#
|
81
119
|
def thru_coderay #:nodoc:
|
82
120
|
gsub %r{<(code)(.*?)>(.*?)</\1>}m do
|
83
|
-
atts, code = $2, CGI.unescapeHTML($3).sub(/\A\r?\n/, '')
|
121
|
+
elem, atts, code = $1, $2, CGI.unescapeHTML($3).sub(/\A\r?\n/, '')
|
84
122
|
lang = atts[/\blang=('|")(.*?)\1/i, 2] || :ruby
|
85
123
|
|
86
|
-
|
87
|
-
|
124
|
+
body = CodeRay.scan(code, lang).html(:css => :style)
|
125
|
+
|
126
|
+
if code =~ /\n/
|
127
|
+
span = :para
|
128
|
+
head = "<ins><pre"
|
129
|
+
tail = "</pre></ins>"
|
130
|
+
|
131
|
+
else
|
132
|
+
span = :line
|
133
|
+
head = "<#{elem}"
|
134
|
+
tail = "</#{elem}>"
|
135
|
+
end
|
88
136
|
|
89
|
-
%{
|
137
|
+
%{#{head} class="#{span}"#{atts}>#{body}#{tail}}
|
90
138
|
end
|
91
139
|
end
|
92
140
|
|
93
141
|
private
|
94
142
|
|
143
|
+
##
|
95
144
|
# Protects the given tags in the given input, passes
|
96
145
|
# that protected input to the given block, restores the
|
97
146
|
# given tags in the result of the block and returns it.
|
98
147
|
#
|
99
|
-
# verbatim
|
100
|
-
#
|
101
|
-
#
|
148
|
+
# [verbatim]
|
149
|
+
# If true, the content of the elments having the given tags will not be
|
150
|
+
# temporarily altered so that process nested elements can be processed.
|
102
151
|
#
|
103
|
-
def with_protected_tags input,
|
152
|
+
def with_protected_tags input, tag_defs, verbatim #:yields: input
|
104
153
|
raise ArgumentError unless block_given?
|
105
154
|
|
106
155
|
input = input.dup
|
107
156
|
escapes = {}
|
108
157
|
|
109
158
|
# protect the given tags by escaping them
|
110
|
-
|
159
|
+
tag_defs.each_key do |tag|
|
111
160
|
input.gsub! %r{(<#{tag}.*?>)(.*?)(</#{tag}>)}m do
|
112
161
|
head, body, tail = $1, $2, $3
|
113
162
|
|
@@ -123,7 +172,7 @@ class String
|
|
123
172
|
head << CGI.escapeHTML(CGI.unescapeHTML(body)) << tail
|
124
173
|
end
|
125
174
|
|
126
|
-
escaped =
|
175
|
+
escaped = calc_digest(original)
|
127
176
|
escapes[escaped] = original
|
128
177
|
|
129
178
|
escaped
|
@@ -136,12 +185,36 @@ class String
|
|
136
185
|
# restore the protected tags by unescaping them
|
137
186
|
until escapes.empty?
|
138
187
|
escapes.each_pair do |esc, orig|
|
139
|
-
|
140
|
-
|
141
|
-
|
188
|
+
tag = orig[/<\/(.+?)>\s*\z/, 1].to_sym
|
189
|
+
raise ArgumentError, tag unless tag_defs.key? tag
|
190
|
+
|
191
|
+
restore_ok =
|
192
|
+
case tag_defs[tag]
|
193
|
+
when :inline
|
194
|
+
# process inline elements normally
|
195
|
+
output.gsub! esc, orig
|
196
|
+
|
197
|
+
when :block
|
198
|
+
# pull block-level elements out of paragraph tag added by Maruku
|
199
|
+
output.gsub!(/(<p>\s*)?#{Regexp.quote esc}/){ orig + $1.to_s }
|
200
|
+
end
|
201
|
+
|
202
|
+
escapes.delete esc if restore_ok
|
142
203
|
end
|
143
204
|
end
|
144
205
|
|
145
206
|
output
|
146
207
|
end
|
208
|
+
|
209
|
+
##
|
210
|
+
# Returns a digest of the given string that
|
211
|
+
# will not be altered by String#to_xhtml.
|
212
|
+
#
|
213
|
+
def calc_digest input
|
214
|
+
Digest::SHA1.hexdigest(input.to_s).
|
215
|
+
|
216
|
+
# XXX: surround all digits with alphabets so
|
217
|
+
# Maruku doesn't change them into HTML
|
218
|
+
gsub(/\d/, 'z\&z')
|
219
|
+
end
|
147
220
|
end
|