voloko-sdoc 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/rdoc/History.txt +254 -0
- data/rdoc/Manifest.txt +126 -0
- data/rdoc/README.txt +47 -0
- data/rdoc/RI.txt +58 -0
- data/rdoc/Rakefile +70 -0
- data/rdoc/bin/rdoc +35 -0
- data/rdoc/bin/ri +5 -0
- data/rdoc/lib/rdoc/alias.rb +54 -0
- data/rdoc/lib/rdoc/anon_class.rb +10 -0
- data/rdoc/lib/rdoc/any_method.rb +190 -0
- data/rdoc/lib/rdoc/attr.rb +79 -0
- data/rdoc/lib/rdoc/cache.rb +41 -0
- data/rdoc/lib/rdoc/class_module.rb +87 -0
- data/rdoc/lib/rdoc/code_object.rb +152 -0
- data/rdoc/lib/rdoc/code_objects.rb +23 -0
- data/rdoc/lib/rdoc/constant.rb +36 -0
- data/rdoc/lib/rdoc/context.rb +712 -0
- data/rdoc/lib/rdoc/diagram.rb +340 -0
- data/rdoc/lib/rdoc/dot.rb +249 -0
- data/rdoc/lib/rdoc/generator/darkfish.rb +455 -0
- data/rdoc/lib/rdoc/generator/markup.rb +194 -0
- data/rdoc/lib/rdoc/generator/ri.rb +230 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/classpage.rhtml +281 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/filepage.rhtml +112 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/brick.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/brick_link.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/bug.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/bullet_black.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/date.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/find.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/macFFBgHack.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/package.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/page_green.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/page_white_text.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/page_white_width.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/plugin.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/ruby.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/tag_green.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/wrench.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/wrench_orange.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/images/zoom.png +0 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/index.rhtml +64 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/js/darkfish.js +116 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/js/jquery.js +32 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/js/quicksearch.js +114 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/js/thickbox-compressed.js +10 -0
- data/rdoc/lib/rdoc/generator/template/darkfish/rdoc.css +696 -0
- data/rdoc/lib/rdoc/generator.rb +8 -0
- data/rdoc/lib/rdoc/ghost_method.rb +8 -0
- data/rdoc/lib/rdoc/include.rb +39 -0
- data/rdoc/lib/rdoc/known_classes.rb +68 -0
- data/rdoc/lib/rdoc/markup/attribute_manager.rb +311 -0
- data/rdoc/lib/rdoc/markup/formatter.rb +25 -0
- data/rdoc/lib/rdoc/markup/fragments.rb +377 -0
- data/rdoc/lib/rdoc/markup/inline.rb +126 -0
- data/rdoc/lib/rdoc/markup/lines.rb +156 -0
- data/rdoc/lib/rdoc/markup/preprocess.rb +80 -0
- data/rdoc/lib/rdoc/markup/to_flow.rb +211 -0
- data/rdoc/lib/rdoc/markup/to_html.rb +406 -0
- data/rdoc/lib/rdoc/markup/to_html_crossref.rb +140 -0
- data/rdoc/lib/rdoc/markup/to_latex.rb +328 -0
- data/rdoc/lib/rdoc/markup/to_test.rb +53 -0
- data/rdoc/lib/rdoc/markup/to_texinfo.rb +73 -0
- data/rdoc/lib/rdoc/markup.rb +378 -0
- data/rdoc/lib/rdoc/meta_method.rb +8 -0
- data/rdoc/lib/rdoc/normal_class.rb +18 -0
- data/rdoc/lib/rdoc/normal_module.rb +34 -0
- data/rdoc/lib/rdoc/options.rb +542 -0
- data/rdoc/lib/rdoc/parser/c.rb +678 -0
- data/rdoc/lib/rdoc/parser/perl.rb +165 -0
- data/rdoc/lib/rdoc/parser/ruby.rb +2904 -0
- data/rdoc/lib/rdoc/parser/simple.rb +39 -0
- data/rdoc/lib/rdoc/parser.rb +138 -0
- data/rdoc/lib/rdoc/rdoc.rb +375 -0
- data/rdoc/lib/rdoc/require.rb +32 -0
- data/rdoc/lib/rdoc/ri/cache.rb +187 -0
- data/rdoc/lib/rdoc/ri/descriptions.rb +156 -0
- data/rdoc/lib/rdoc/ri/display.rb +340 -0
- data/rdoc/lib/rdoc/ri/driver.rb +828 -0
- data/rdoc/lib/rdoc/ri/formatter.rb +654 -0
- data/rdoc/lib/rdoc/ri/paths.rb +93 -0
- data/rdoc/lib/rdoc/ri/reader.rb +106 -0
- data/rdoc/lib/rdoc/ri/util.rb +79 -0
- data/rdoc/lib/rdoc/ri/writer.rb +68 -0
- data/rdoc/lib/rdoc/ri.rb +8 -0
- data/rdoc/lib/rdoc/single_class.rb +8 -0
- data/rdoc/lib/rdoc/stats.rb +178 -0
- data/rdoc/lib/rdoc/task.rb +276 -0
- data/rdoc/lib/rdoc/tokenstream.rb +33 -0
- data/rdoc/lib/rdoc/top_level.rb +242 -0
- data/rdoc/lib/rdoc.rb +398 -0
- metadata +1 -1
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'rdoc/markup'
|
2
|
+
|
3
|
+
##
|
4
|
+
# Handle common directives that can occur in a block of text:
|
5
|
+
#
|
6
|
+
# : include : filename
|
7
|
+
|
8
|
+
class RDoc::Markup::PreProcess
|
9
|
+
|
10
|
+
##
|
11
|
+
# Creates a new pre-processor for +input_file_name+ that will look for
|
12
|
+
# included files in +include_path+
|
13
|
+
|
14
|
+
def initialize(input_file_name, include_path)
|
15
|
+
@input_file_name = input_file_name
|
16
|
+
@include_path = include_path
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Look for common options in a chunk of text. Options that we don't handle
|
21
|
+
# are yielded to the caller.
|
22
|
+
|
23
|
+
def handle(text)
|
24
|
+
text.gsub!(/^([ \t]*#?[ \t]*):(\w+):([ \t]*)(.+)?\n/) do
|
25
|
+
next $& if $3.empty? and $4 and $4[0, 1] == ':'
|
26
|
+
|
27
|
+
prefix = $1
|
28
|
+
directive = $2.downcase
|
29
|
+
param = $4
|
30
|
+
|
31
|
+
case directive
|
32
|
+
when 'include' then
|
33
|
+
filename = param.split[0]
|
34
|
+
include_file filename, prefix
|
35
|
+
|
36
|
+
else
|
37
|
+
result = yield directive, param
|
38
|
+
result = "#{prefix}:#{directive}: #{param}\n" unless result
|
39
|
+
result
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
##
|
47
|
+
# Include a file, indenting it correctly.
|
48
|
+
|
49
|
+
def include_file(name, indent)
|
50
|
+
if full_name = find_include_file(name) then
|
51
|
+
content = File.read full_name
|
52
|
+
|
53
|
+
# strip leading '#'s, but only if all lines start with them
|
54
|
+
if content =~ /^[^#]/ then
|
55
|
+
content.gsub(/^/, indent)
|
56
|
+
else
|
57
|
+
content.gsub(/^#?/, indent)
|
58
|
+
end
|
59
|
+
else
|
60
|
+
$stderr.puts "Couldn't find file to include '#{name}' from #{@input_file_name}"
|
61
|
+
''
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Look for the given file in the directory containing the current file,
|
67
|
+
# and then in each of the directories specified in the RDOC_INCLUDE path
|
68
|
+
|
69
|
+
def find_include_file(name)
|
70
|
+
to_search = [ File.dirname(@input_file_name) ].concat @include_path
|
71
|
+
to_search.each do |dir|
|
72
|
+
full_name = File.join(dir, name)
|
73
|
+
stat = File.stat(full_name) rescue next
|
74
|
+
return full_name if stat.readable?
|
75
|
+
end
|
76
|
+
nil
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
@@ -0,0 +1,211 @@
|
|
1
|
+
require 'rdoc/markup/formatter'
|
2
|
+
require 'rdoc/markup/fragments'
|
3
|
+
require 'rdoc/markup/inline'
|
4
|
+
require 'cgi'
|
5
|
+
|
6
|
+
class RDoc::Markup
|
7
|
+
|
8
|
+
module Flow
|
9
|
+
|
10
|
+
##
|
11
|
+
# Paragraph
|
12
|
+
|
13
|
+
P = Struct.new(:body)
|
14
|
+
|
15
|
+
##
|
16
|
+
# Verbatim
|
17
|
+
|
18
|
+
VERB = Struct.new(:body)
|
19
|
+
|
20
|
+
##
|
21
|
+
# Horizontal rule
|
22
|
+
|
23
|
+
RULE = Struct.new(:width)
|
24
|
+
|
25
|
+
##
|
26
|
+
# List
|
27
|
+
|
28
|
+
class LIST
|
29
|
+
attr_reader :type, :contents
|
30
|
+
def initialize(type)
|
31
|
+
@type = type
|
32
|
+
@contents = []
|
33
|
+
end
|
34
|
+
def <<(stuff)
|
35
|
+
@contents << stuff
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# List item
|
41
|
+
|
42
|
+
LI = Struct.new(:label, :body)
|
43
|
+
|
44
|
+
##
|
45
|
+
# Heading
|
46
|
+
|
47
|
+
H = Struct.new(:level, :text)
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class ToFlow < RDoc::Markup::Formatter
|
52
|
+
|
53
|
+
LIST_TYPE_TO_HTML = {
|
54
|
+
:BULLET => [ "<ul>", "</ul>" ],
|
55
|
+
:NUMBER => [ "<ol>", "</ol>" ],
|
56
|
+
:UPPERALPHA => [ "<ol>", "</ol>" ],
|
57
|
+
:LOWERALPHA => [ "<ol>", "</ol>" ],
|
58
|
+
:LABELED => [ "<dl>", "</dl>" ],
|
59
|
+
:NOTE => [ "<table>", "</table>" ],
|
60
|
+
}
|
61
|
+
|
62
|
+
InlineTag = Struct.new(:bit, :on, :off)
|
63
|
+
|
64
|
+
def initialize
|
65
|
+
super
|
66
|
+
|
67
|
+
init_tags
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Set up the standard mapping of attributes to HTML tags
|
72
|
+
|
73
|
+
def init_tags
|
74
|
+
@attr_tags = [
|
75
|
+
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
|
76
|
+
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:TT), "<tt>", "</tt>"),
|
77
|
+
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:EM), "<em>", "</em>"),
|
78
|
+
]
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Add a new set of HTML tags for an attribute. We allow separate start and
|
83
|
+
# end tags for flexibility
|
84
|
+
|
85
|
+
def add_tag(name, start, stop)
|
86
|
+
@attr_tags << InlineTag.new(RDoc::Markup::Attribute.bitmap_for(name), start, stop)
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Given an HTML tag, decorate it with class information and the like if
|
91
|
+
# required. This is a no-op in the base class, but is overridden in HTML
|
92
|
+
# output classes that implement style sheets
|
93
|
+
|
94
|
+
def annotate(tag)
|
95
|
+
tag
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# :section: Visitor
|
100
|
+
|
101
|
+
def start_accepting
|
102
|
+
@res = []
|
103
|
+
@list_stack = []
|
104
|
+
end
|
105
|
+
|
106
|
+
def end_accepting
|
107
|
+
@res
|
108
|
+
end
|
109
|
+
|
110
|
+
def accept_paragraph(am, fragment)
|
111
|
+
@res << Flow::P.new((convert_flow(am.flow(fragment.txt))))
|
112
|
+
end
|
113
|
+
|
114
|
+
def accept_verbatim(am, fragment)
|
115
|
+
@res << Flow::VERB.new((convert_flow(am.flow(fragment.txt))))
|
116
|
+
end
|
117
|
+
|
118
|
+
def accept_rule(am, fragment)
|
119
|
+
size = fragment.param
|
120
|
+
size = 10 if size > 10
|
121
|
+
@res << Flow::RULE.new(size)
|
122
|
+
end
|
123
|
+
|
124
|
+
def accept_list_start(am, fragment)
|
125
|
+
@list_stack.push(@res)
|
126
|
+
list = Flow::LIST.new(fragment.type)
|
127
|
+
@res << list
|
128
|
+
@res = list
|
129
|
+
end
|
130
|
+
|
131
|
+
def accept_list_end(am, fragment)
|
132
|
+
@res = @list_stack.pop
|
133
|
+
end
|
134
|
+
|
135
|
+
def accept_list_item(am, fragment)
|
136
|
+
@res << Flow::LI.new(fragment.param, convert_flow(am.flow(fragment.txt)))
|
137
|
+
end
|
138
|
+
|
139
|
+
def accept_blank_line(am, fragment)
|
140
|
+
# @res << annotate("<p />") << "\n"
|
141
|
+
end
|
142
|
+
|
143
|
+
def accept_heading(am, fragment)
|
144
|
+
@res << Flow::H.new(fragment.head_level, convert_flow(am.flow(fragment.txt)))
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def on_tags(res, item)
|
150
|
+
attr_mask = item.turn_on
|
151
|
+
return if attr_mask.zero?
|
152
|
+
|
153
|
+
@attr_tags.each do |tag|
|
154
|
+
if attr_mask & tag.bit != 0
|
155
|
+
res << annotate(tag.on)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def off_tags(res, item)
|
161
|
+
attr_mask = item.turn_off
|
162
|
+
return if attr_mask.zero?
|
163
|
+
|
164
|
+
@attr_tags.reverse_each do |tag|
|
165
|
+
if attr_mask & tag.bit != 0
|
166
|
+
res << annotate(tag.off)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def convert_flow(flow)
|
172
|
+
res = ""
|
173
|
+
flow.each do |item|
|
174
|
+
case item
|
175
|
+
when String
|
176
|
+
res << convert_string(item)
|
177
|
+
when AttrChanger
|
178
|
+
off_tags(res, item)
|
179
|
+
on_tags(res, item)
|
180
|
+
when Special
|
181
|
+
res << convert_special(item)
|
182
|
+
else
|
183
|
+
raise "Unknown flow element: #{item.inspect}"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
res
|
187
|
+
end
|
188
|
+
|
189
|
+
def convert_string(item)
|
190
|
+
CGI.escapeHTML(item)
|
191
|
+
end
|
192
|
+
|
193
|
+
def convert_special(special)
|
194
|
+
handled = false
|
195
|
+
Attribute.each_name_of(special.type) do |name|
|
196
|
+
method_name = "handle_special_#{name}"
|
197
|
+
if self.respond_to? method_name
|
198
|
+
special.text = send(method_name, special)
|
199
|
+
handled = true
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
raise "Unhandled special: #{special}" unless handled
|
204
|
+
|
205
|
+
special.text
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
|
@@ -0,0 +1,406 @@
|
|
1
|
+
require 'rdoc/markup/formatter'
|
2
|
+
require 'rdoc/markup/fragments'
|
3
|
+
require 'rdoc/markup/inline'
|
4
|
+
|
5
|
+
require 'cgi'
|
6
|
+
|
7
|
+
class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
8
|
+
|
9
|
+
LIST_TYPE_TO_HTML = {
|
10
|
+
:BULLET => %w[<ul> </ul>],
|
11
|
+
:NUMBER => %w[<ol> </ol>],
|
12
|
+
:UPPERALPHA => %w[<ol> </ol>],
|
13
|
+
:LOWERALPHA => %w[<ol> </ol>],
|
14
|
+
:LABELED => %w[<dl> </dl>],
|
15
|
+
:NOTE => %w[<table> </table>],
|
16
|
+
}
|
17
|
+
|
18
|
+
InlineTag = Struct.new(:bit, :on, :off)
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
super
|
22
|
+
|
23
|
+
# @in_tt - tt nested levels count
|
24
|
+
# @tt_bit - cache
|
25
|
+
@in_tt = 0
|
26
|
+
@tt_bit = RDoc::Markup::Attribute.bitmap_for :TT
|
27
|
+
|
28
|
+
# external hyperlinks
|
29
|
+
@markup.add_special(/((link:|https?:|mailto:|ftp:|www\.)\S+\w)/, :HYPERLINK)
|
30
|
+
|
31
|
+
# and links of the form <text>[<url>]
|
32
|
+
@markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\.\S+?\])/, :TIDYLINK)
|
33
|
+
|
34
|
+
init_tags
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Converts a target url to one that is relative to a given path
|
39
|
+
|
40
|
+
def self.gen_relative_url(path, target)
|
41
|
+
from = File.dirname path
|
42
|
+
to, to_file = File.split target
|
43
|
+
|
44
|
+
from = from.split "/"
|
45
|
+
to = to.split "/"
|
46
|
+
|
47
|
+
from.delete '.'
|
48
|
+
to.delete '.'
|
49
|
+
|
50
|
+
while from.size > 0 and to.size > 0 and from[0] == to[0] do
|
51
|
+
from.shift
|
52
|
+
to.shift
|
53
|
+
end
|
54
|
+
|
55
|
+
from.fill ".."
|
56
|
+
from.concat to
|
57
|
+
from << to_file
|
58
|
+
File.join(*from)
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Generate a hyperlink for url, labeled with text. Handle the
|
63
|
+
# special cases for img: and link: described under handle_special_HYPERLINK
|
64
|
+
|
65
|
+
def gen_url(url, text)
|
66
|
+
if url =~ /([A-Za-z]+):(.*)/ then
|
67
|
+
type = $1
|
68
|
+
path = $2
|
69
|
+
else
|
70
|
+
type = "http"
|
71
|
+
path = url
|
72
|
+
url = "http://#{url}"
|
73
|
+
end
|
74
|
+
|
75
|
+
if type == "link" then
|
76
|
+
url = if path[0, 1] == '#' then # is this meaningful?
|
77
|
+
path
|
78
|
+
else
|
79
|
+
self.class.gen_relative_url @from_path, path
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
if (type == "http" or type == "link") and
|
84
|
+
url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then
|
85
|
+
"<img src=\"#{url}\" />"
|
86
|
+
else
|
87
|
+
"<a href=\"#{url}\">#{text.sub(%r{^#{type}:/*}, '')}</a>"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# And we're invoked with a potential external hyperlink mailto:
|
93
|
+
# just gets inserted. http: links are checked to see if they
|
94
|
+
# reference an image. If so, that image gets inserted using an
|
95
|
+
# <img> tag. Otherwise a conventional <a href> is used. We also
|
96
|
+
# support a special type of hyperlink, link:, which is a reference
|
97
|
+
# to a local file whose path is relative to the --op directory.
|
98
|
+
|
99
|
+
def handle_special_HYPERLINK(special)
|
100
|
+
url = special.text
|
101
|
+
gen_url url, url
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Here's a hypedlink where the label is different to the URL
|
106
|
+
# <label>[url] or {long label}[url]
|
107
|
+
|
108
|
+
def handle_special_TIDYLINK(special)
|
109
|
+
text = special.text
|
110
|
+
|
111
|
+
return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/
|
112
|
+
|
113
|
+
label = $1
|
114
|
+
url = $2
|
115
|
+
gen_url url, label
|
116
|
+
end
|
117
|
+
|
118
|
+
##
|
119
|
+
# are we currently inside tt tags?
|
120
|
+
|
121
|
+
def in_tt?
|
122
|
+
@in_tt > 0
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# is +tag+ a tt tag?
|
127
|
+
|
128
|
+
def tt?(tag)
|
129
|
+
tag.bit == @tt_bit
|
130
|
+
end
|
131
|
+
|
132
|
+
##
|
133
|
+
# Set up the standard mapping of attributes to HTML tags
|
134
|
+
|
135
|
+
def init_tags
|
136
|
+
@attr_tags = [
|
137
|
+
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
|
138
|
+
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:TT), "<tt>", "</tt>"),
|
139
|
+
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:EM), "<em>", "</em>"),
|
140
|
+
]
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# Add a new set of HTML tags for an attribute. We allow separate start and
|
145
|
+
# end tags for flexibility.
|
146
|
+
|
147
|
+
def add_tag(name, start, stop)
|
148
|
+
@attr_tags << InlineTag.new(RDoc::Markup::Attribute.bitmap_for(name), start, stop)
|
149
|
+
end
|
150
|
+
|
151
|
+
##
|
152
|
+
# Given an HTML tag, decorate it with class information and the like if
|
153
|
+
# required. This is a no-op in the base class, but is overridden in HTML
|
154
|
+
# output classes that implement style sheets.
|
155
|
+
|
156
|
+
def annotate(tag)
|
157
|
+
tag
|
158
|
+
end
|
159
|
+
|
160
|
+
##
|
161
|
+
# This is a higher speed (if messier) version of wrap
|
162
|
+
|
163
|
+
def wrap(txt, line_len = 76)
|
164
|
+
res = ""
|
165
|
+
sp = 0
|
166
|
+
ep = txt.length
|
167
|
+
while sp < ep
|
168
|
+
# scan back for a space
|
169
|
+
p = sp + line_len - 1
|
170
|
+
if p >= ep
|
171
|
+
p = ep
|
172
|
+
else
|
173
|
+
while p > sp and txt[p] != ?\s
|
174
|
+
p -= 1
|
175
|
+
end
|
176
|
+
if p <= sp
|
177
|
+
p = sp + line_len
|
178
|
+
while p < ep and txt[p] != ?\s
|
179
|
+
p += 1
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
res << txt[sp...p] << "\n"
|
184
|
+
sp = p
|
185
|
+
sp += 1 while sp < ep and txt[sp] == ?\s
|
186
|
+
end
|
187
|
+
res
|
188
|
+
end
|
189
|
+
|
190
|
+
##
|
191
|
+
# :section: Visitor
|
192
|
+
|
193
|
+
def start_accepting
|
194
|
+
@res = ""
|
195
|
+
@in_list_entry = []
|
196
|
+
end
|
197
|
+
|
198
|
+
def end_accepting
|
199
|
+
@res
|
200
|
+
end
|
201
|
+
|
202
|
+
def accept_paragraph(am, fragment)
|
203
|
+
@res << annotate("<p>") + "\n"
|
204
|
+
@res << wrap(convert_flow(am.flow(fragment.txt)))
|
205
|
+
@res << annotate("</p>") + "\n"
|
206
|
+
end
|
207
|
+
|
208
|
+
def accept_verbatim(am, fragment)
|
209
|
+
@res << annotate("<pre>") + "\n"
|
210
|
+
@res << CGI.escapeHTML(fragment.txt)
|
211
|
+
@res << annotate("</pre>") << "\n"
|
212
|
+
end
|
213
|
+
|
214
|
+
def accept_rule(am, fragment)
|
215
|
+
size = fragment.param
|
216
|
+
size = 10 if size > 10
|
217
|
+
@res << "<hr size=\"#{size}\"></hr>"
|
218
|
+
end
|
219
|
+
|
220
|
+
def accept_list_start(am, fragment)
|
221
|
+
@res << html_list_name(fragment.type, true) << "\n"
|
222
|
+
@in_list_entry.push false
|
223
|
+
end
|
224
|
+
|
225
|
+
def accept_list_end(am, fragment)
|
226
|
+
if tag = @in_list_entry.pop
|
227
|
+
@res << annotate(tag) << "\n"
|
228
|
+
end
|
229
|
+
@res << html_list_name(fragment.type, false) << "\n"
|
230
|
+
end
|
231
|
+
|
232
|
+
def accept_list_item(am, fragment)
|
233
|
+
if tag = @in_list_entry.last
|
234
|
+
@res << annotate(tag) << "\n"
|
235
|
+
end
|
236
|
+
|
237
|
+
@res << list_item_start(am, fragment)
|
238
|
+
|
239
|
+
@res << wrap(convert_flow(am.flow(fragment.txt))) << "\n"
|
240
|
+
|
241
|
+
@in_list_entry[-1] = list_end_for(fragment.type)
|
242
|
+
end
|
243
|
+
|
244
|
+
def accept_blank_line(am, fragment)
|
245
|
+
# @res << annotate("<p />") << "\n"
|
246
|
+
end
|
247
|
+
|
248
|
+
def accept_heading(am, fragment)
|
249
|
+
@res << convert_heading(fragment.head_level, am.flow(fragment.txt))
|
250
|
+
end
|
251
|
+
|
252
|
+
private
|
253
|
+
|
254
|
+
def on_tags(res, item)
|
255
|
+
attr_mask = item.turn_on
|
256
|
+
return if attr_mask.zero?
|
257
|
+
|
258
|
+
@attr_tags.each do |tag|
|
259
|
+
if attr_mask & tag.bit != 0
|
260
|
+
res << annotate(tag.on)
|
261
|
+
@in_tt += 1 if tt?(tag)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def off_tags(res, item)
|
267
|
+
attr_mask = item.turn_off
|
268
|
+
return if attr_mask.zero?
|
269
|
+
|
270
|
+
@attr_tags.reverse_each do |tag|
|
271
|
+
if attr_mask & tag.bit != 0
|
272
|
+
@in_tt -= 1 if tt?(tag)
|
273
|
+
res << annotate(tag.off)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def convert_flow(flow)
|
279
|
+
res = ""
|
280
|
+
|
281
|
+
flow.each do |item|
|
282
|
+
case item
|
283
|
+
when String
|
284
|
+
res << convert_string(item)
|
285
|
+
when RDoc::Markup::AttrChanger
|
286
|
+
off_tags(res, item)
|
287
|
+
on_tags(res, item)
|
288
|
+
when RDoc::Markup::Special
|
289
|
+
res << convert_special(item)
|
290
|
+
else
|
291
|
+
raise "Unknown flow element: #{item.inspect}"
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
res
|
296
|
+
end
|
297
|
+
|
298
|
+
def convert_string(item)
|
299
|
+
in_tt? ? convert_string_simple(item) : convert_string_fancy(item)
|
300
|
+
end
|
301
|
+
|
302
|
+
def convert_string_simple(item)
|
303
|
+
CGI.escapeHTML item
|
304
|
+
end
|
305
|
+
|
306
|
+
##
|
307
|
+
# some of these patterns are taken from SmartyPants...
|
308
|
+
|
309
|
+
def convert_string_fancy(item)
|
310
|
+
# convert ampersand before doing anything else
|
311
|
+
item.gsub(/&/, '&').
|
312
|
+
|
313
|
+
# convert -- to em-dash, (-- to en-dash)
|
314
|
+
gsub(/---?/, '—'). #gsub(/--/, '–').
|
315
|
+
|
316
|
+
# convert ... to elipsis (and make sure .... becomes .<elipsis>)
|
317
|
+
gsub(/\.\.\.\./, '.…').gsub(/\.\.\./, '…').
|
318
|
+
|
319
|
+
# convert single closing quote
|
320
|
+
gsub(%r{([^ \t\r\n\[\{\(])\'}, '\1’'). # }
|
321
|
+
gsub(%r{\'(?=\W|s\b)}, '’').
|
322
|
+
|
323
|
+
# convert single opening quote
|
324
|
+
gsub(/'/, '‘').
|
325
|
+
|
326
|
+
# convert double closing quote
|
327
|
+
gsub(%r{([^ \t\r\n\[\{\(])\"(?=\W)}, '\1”'). # }
|
328
|
+
|
329
|
+
# convert double opening quote
|
330
|
+
gsub(/"/, '“').
|
331
|
+
|
332
|
+
# convert copyright
|
333
|
+
gsub(/\(c\)/, '©').
|
334
|
+
|
335
|
+
# convert registered trademark
|
336
|
+
gsub(/\(r\)/, '®')
|
337
|
+
end
|
338
|
+
|
339
|
+
def convert_special(special)
|
340
|
+
handled = false
|
341
|
+
RDoc::Markup::Attribute.each_name_of(special.type) do |name|
|
342
|
+
method_name = "handle_special_#{name}"
|
343
|
+
if self.respond_to? method_name
|
344
|
+
special.text = send(method_name, special)
|
345
|
+
handled = true
|
346
|
+
end
|
347
|
+
end
|
348
|
+
raise "Unhandled special: #{special}" unless handled
|
349
|
+
special.text
|
350
|
+
end
|
351
|
+
|
352
|
+
def convert_heading(level, flow)
|
353
|
+
res =
|
354
|
+
annotate("<h#{level}>") +
|
355
|
+
convert_flow(flow) +
|
356
|
+
annotate("</h#{level}>\n")
|
357
|
+
end
|
358
|
+
|
359
|
+
def html_list_name(list_type, is_open_tag)
|
360
|
+
tags = LIST_TYPE_TO_HTML[list_type] || raise("Invalid list type: #{list_type.inspect}")
|
361
|
+
annotate(tags[ is_open_tag ? 0 : 1])
|
362
|
+
end
|
363
|
+
|
364
|
+
def list_item_start(am, fragment)
|
365
|
+
case fragment.type
|
366
|
+
when :BULLET, :NUMBER then
|
367
|
+
annotate("<li>")
|
368
|
+
|
369
|
+
when :UPPERALPHA then
|
370
|
+
annotate("<li type=\"A\">")
|
371
|
+
|
372
|
+
when :LOWERALPHA then
|
373
|
+
annotate("<li type=\"a\">")
|
374
|
+
|
375
|
+
when :LABELED then
|
376
|
+
annotate("<dt>") +
|
377
|
+
convert_flow(am.flow(fragment.param)) +
|
378
|
+
annotate("</dt>") +
|
379
|
+
annotate("<dd>")
|
380
|
+
|
381
|
+
when :NOTE then
|
382
|
+
annotate("<tr>") +
|
383
|
+
annotate("<td valign=\"top\">") +
|
384
|
+
convert_flow(am.flow(fragment.param)) +
|
385
|
+
annotate("</td>") +
|
386
|
+
annotate("<td>")
|
387
|
+
else
|
388
|
+
raise "Invalid list type"
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
def list_end_for(fragment_type)
|
393
|
+
case fragment_type
|
394
|
+
when :BULLET, :NUMBER, :UPPERALPHA, :LOWERALPHA then
|
395
|
+
"</li>"
|
396
|
+
when :LABELED then
|
397
|
+
"</dd>"
|
398
|
+
when :NOTE then
|
399
|
+
"</td></tr>"
|
400
|
+
else
|
401
|
+
raise "Invalid list type"
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
end
|
406
|
+
|