rd2odt 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/FUTURE +63 -0
  2. data/LICENSE +21 -0
  3. data/NEWS +42 -0
  4. data/README +78 -0
  5. data/Rakefile +51 -0
  6. data/bin/rd2odt +4 -0
  7. data/doc/sample/body-text.rd +5 -0
  8. data/doc/sample/enum-list-over-headline-multi-level.rd +10 -0
  9. data/doc/sample/enum-list-over-headline.rd +9 -0
  10. data/doc/sample/enum-list-over-item-list-multi-level-2.rd +9 -0
  11. data/doc/sample/enum-list-over-item-list-multi-level.rd +8 -0
  12. data/doc/sample/enum-list-over-item-list.rd +7 -0
  13. data/doc/sample/headline.rd +60 -0
  14. data/doc/sample/include-file-figure.odt +0 -0
  15. data/doc/sample/include-file-ole-object.odt +0 -0
  16. data/doc/sample/include-file-original-styled-text.odt +0 -0
  17. data/doc/sample/include-file-shape.odt +0 -0
  18. data/doc/sample/include-file-simple-styled-text.odt +0 -0
  19. data/doc/sample/include-file-simple-text.odt +0 -0
  20. data/doc/sample/include-file-table.odt +0 -0
  21. data/doc/sample/include.rd +21 -0
  22. data/doc/sample/list.rd +22 -0
  23. data/doc/sample/multi-paragraph.rd +12 -0
  24. data/doc/sample/page-break.odt +0 -0
  25. data/doc/sample/verbatim.rd +8 -0
  26. data/doc/sample.rd.ja +75 -0
  27. data/doc/sample.rd.ja.ott +0 -0
  28. data/doc/sample.rd.ja.pdf +0 -0
  29. data/doc/specification.ja.rd +35 -0
  30. data/lib/rd2odt/rdtool/NOTICE.rd2odt +8 -0
  31. data/lib/rd2odt/rdtool/README.rd +50 -0
  32. data/lib/rd2odt/rdtool/README.rd.ja +53 -0
  33. data/lib/rd2odt/rdtool/rd/block-element.rb +114 -0
  34. data/lib/rd2odt/rdtool/rd/complex-list-item.rb +65 -0
  35. data/lib/rd2odt/rdtool/rd/desclist.rb +55 -0
  36. data/lib/rd2odt/rdtool/rd/document-struct.rb +46 -0
  37. data/lib/rd2odt/rdtool/rd/element.rb +160 -0
  38. data/lib/rd2odt/rdtool/rd/filter.rb +255 -0
  39. data/lib/rd2odt/rdtool/rd/inline-element.rb +233 -0
  40. data/lib/rd2odt/rdtool/rd/labeled-element.rb +14 -0
  41. data/lib/rd2odt/rdtool/rd/list.rb +57 -0
  42. data/lib/rd2odt/rdtool/rd/loose-struct.rb +11 -0
  43. data/lib/rd2odt/rdtool/rd/methodlist.rb +57 -0
  44. data/lib/rd2odt/rdtool/rd/output-format-visitor.rb +28 -0
  45. data/lib/rd2odt/rdtool/rd/package.rb +4 -0
  46. data/lib/rd2odt/rdtool/rd/parser-util.rb +14 -0
  47. data/lib/rd2odt/rdtool/rd/rbl-file.rb +69 -0
  48. data/lib/rd2odt/rdtool/rd/rbl-suite.rb +37 -0
  49. data/lib/rd2odt/rdtool/rd/rd-struct.rb +86 -0
  50. data/lib/rd2odt/rdtool/rd/rd2html-lib.rb +490 -0
  51. data/lib/rd2odt/rdtool/rd/rd2html-opt.rb +67 -0
  52. data/lib/rd2odt/rdtool/rd/rd2man-lib.rb +241 -0
  53. data/lib/rd2odt/rdtool/rd/rd2rdo-lib.rb +19 -0
  54. data/lib/rd2odt/rdtool/rd/rd2rmi-lib.rb +32 -0
  55. data/lib/rd2odt/rdtool/rd/rdblockparser.tab.rb +1050 -0
  56. data/lib/rd2odt/rdtool/rd/rdfmt.rb +15 -0
  57. data/lib/rd2odt/rdtool/rd/rdinlineparser.tab.rb +1243 -0
  58. data/lib/rd2odt/rdtool/rd/rdvisitor.rb +214 -0
  59. data/lib/rd2odt/rdtool/rd/reference-resolver.rb +114 -0
  60. data/lib/rd2odt/rdtool/rd/search-file.rb +14 -0
  61. data/lib/rd2odt/rdtool/rd/tree.rb +103 -0
  62. data/lib/rd2odt/rdtool/rd/version.rb +39 -0
  63. data/lib/rd2odt/rdtool/rd/visitor.rb +86 -0
  64. data/lib/rd2odt.rb +603 -0
  65. data/rd2odt.gemspec +108 -0
  66. data/setup.rb +1585 -0
  67. data/test/functional/rd2odt-spec.rb +733 -0
  68. data/test/test-helper.rb +93 -0
  69. data/test/unit/rd2odt-spec.rb +831 -0
  70. metadata +122 -0
@@ -0,0 +1,69 @@
1
+ require 'rd/search-file'
2
+
3
+ module RD
4
+ class RBLFile
5
+ include SearchFile
6
+
7
+ SUFFIX = "rbl"
8
+ attr_reader :labels
9
+ attr_reader :filename
10
+
11
+ def initialize(filename)
12
+ @filename = RBLFile.basename(filename)
13
+ @labels = []
14
+ end
15
+
16
+ def RBLFile.create_rbl_file(filename, resolver)
17
+ file = File.open(RBLFile.rbl_file_path(filename), "w")
18
+ file.print(RBLFile.labels_to_string(resolver))
19
+ file.close
20
+ end
21
+
22
+ def RBLFile.rbl_file_path(filename)
23
+ basename(filename) + "." + SUFFIX
24
+ end
25
+
26
+ def RBLFile.basename(path)
27
+ if /\.(rd|rb)$/ === path
28
+ $`
29
+ else
30
+ path
31
+ end
32
+ end
33
+
34
+ def RBLFile.labels_to_string(resolver)
35
+ (resolver.collect do |i|
36
+ i.to_label + " => " + resolver.get_anchor(i)
37
+ end).join("\n")
38
+ end
39
+
40
+ def load_rbl_file(search_paths)
41
+ f = search_file(@filename, search_paths, [SUFFIX])
42
+ raise "RBLFile not found." unless f
43
+ src = File.readlines(f).join("")
44
+ @labels = string_to_labels(src)
45
+ end
46
+
47
+ def string_to_labels(src)
48
+ labels = []
49
+ src.each_line do |i|
50
+ labels << parse_line(i)
51
+ end
52
+ labels
53
+ end
54
+
55
+ def parse_line(src)
56
+ col = src.rindex("=>")
57
+ raise "RBL file parse error." unless col
58
+ label = src[0 .. col - 1].strip
59
+ anchor = src[col + 2 .. -1].strip
60
+ [label, anchor]
61
+ end
62
+
63
+ def refer(label)
64
+ label = @labels.find{|i| i[0] == label}
65
+ return nil unless label
66
+ label[1]
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,37 @@
1
+ require "rd/rbl-file"
2
+
3
+ module RD
4
+ class RBLSuite
5
+ attr_reader :rbl_files
6
+
7
+ def initialize(search_paths)
8
+ @search_paths = search_paths
9
+ @rbl_files = []
10
+ end
11
+
12
+ def refer(label, filename)
13
+ rbl = get_rbl_file(filename)
14
+ [rbl.filename, rbl.refer(label)]
15
+ end
16
+
17
+ def get_rbl_file(filename)
18
+ rbl = @rbl_files.find{|i| i.filename == RBLFile.basename(filename)}
19
+ if rbl
20
+ rbl
21
+ else
22
+ add_rbl_file(filename)
23
+ end
24
+ end
25
+
26
+ def add_rbl_file(filename)
27
+ rbl = RBLFile.new(filename)
28
+ begin
29
+ rbl.load_rbl_file(@search_paths)
30
+ rescue RuntimeError
31
+ ensure
32
+ @rbl_files.push(rbl)
33
+ end
34
+ rbl
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,86 @@
1
+ require 'rd/document-struct'
2
+ require 'rd/tree'
3
+ require 'rd/element'
4
+ require 'rd/block-element'
5
+ require 'rd/list'
6
+ require 'rd/desclist'
7
+ require 'rd/methodlist'
8
+ require 'rd/inline-element'
9
+
10
+ # definition of RD document structure.
11
+
12
+ module RD
13
+ # interface. can be component of ListItem.
14
+ module ListItemComposable
15
+ end
16
+ # interface. can be component of Headline and Reference.
17
+ module LabelComposable
18
+ end
19
+ # interface. can include Inline
20
+ module InlineIncludable
21
+ end
22
+
23
+ class DocumentStructure
24
+ RD = DocumentStructure.new
25
+
26
+ RD.define_relationship(Tree, DocumentElement)
27
+ RD.define_relationship(DocumentElement, BlockElement)
28
+ RD.define_relationship(Headline, LabelComposable)
29
+ RD.define_relationship(TextBlock, InlineElement)
30
+ RD.define_relationship(ItemList, ItemListItem)
31
+ RD.define_relationship(EnumList, EnumListItem)
32
+ RD.define_relationship(DescList, DescListItem)
33
+ RD.define_relationship(MethodList, MethodListItem)
34
+ RD.define_relationship(ListItem, ListItemComposable)
35
+ RD.define_relationship(DescListItem, DescListItem::Term)
36
+ RD.define_relationship(DescListItem::Term, LabelComposable)
37
+ RD.define_relationship(MethodListItem, MethodListItem::Term)
38
+ RD.define_relationship(InlineIncludable, InlineElement)
39
+ RD.define_relationship(Reference, LabelComposable)
40
+ end
41
+
42
+ class TextBlock
43
+ include ListItemComposable
44
+ end
45
+ class Verbatim
46
+ include ListItemComposable
47
+ end
48
+ class ItemList
49
+ include ListItemComposable
50
+ end
51
+ class EnumList
52
+ include ListItemComposable
53
+ end
54
+ class DescList
55
+ include ListItemComposable
56
+ end
57
+ class StringElement
58
+ include LabelComposable
59
+ end
60
+ class Emphasis
61
+ include LabelComposable
62
+ include InlineIncludable
63
+ end
64
+ class Code
65
+ include LabelComposable
66
+ include InlineIncludable
67
+ end
68
+ class Var
69
+ include LabelComposable
70
+ include InlineIncludable
71
+ end
72
+ class Keyboard
73
+ include LabelComposable
74
+ include InlineIncludable
75
+ end
76
+ class Index
77
+ include LabelComposable
78
+ include InlineIncludable
79
+ end
80
+ class Footnote
81
+ include InlineIncludable
82
+ end
83
+ class Verb
84
+ include LabelComposable
85
+ end
86
+ end
@@ -0,0 +1,490 @@
1
+ =begin
2
+ = rd2html-lib.rb
3
+ =end
4
+
5
+ require "cgi"
6
+ require "rd/rdvisitor"
7
+ require "rd/version"
8
+
9
+ module RD
10
+ class RD2HTMLVisitor < RDVisitor
11
+ include MethodParse
12
+
13
+ SYSTEM_NAME = "RDtool -- RD2HTMLVisitor"
14
+ SYSTEM_VERSION = "$Version: 0.6.21$" #"
15
+ VERSION = Version.new_from_version_string(SYSTEM_NAME, SYSTEM_VERSION)
16
+
17
+ def self.version
18
+ VERSION
19
+ end
20
+
21
+ # must-have constants
22
+ OUTPUT_SUFFIX = "html"
23
+ INCLUDE_SUFFIX = ["html"]
24
+
25
+ METACHAR = { "<" => "&lt;", ">" => "&gt;", "&" => "&amp;" }
26
+
27
+ attr_accessor :css
28
+ attr_accessor :charset
29
+ alias charcode charset
30
+ alias charcode= charset=
31
+ attr_accessor :lang
32
+ attr_accessor :title
33
+ attr_reader :html_link_rel
34
+ attr_reader :html_link_rev
35
+ attr_accessor :use_old_anchor
36
+ # output external Label file.
37
+ attr_accessor :output_rbl
38
+
39
+ attr_reader :footnotes
40
+ attr_reader :foottexts
41
+
42
+ def initialize
43
+ @css = nil
44
+ @charset = nil
45
+ @lang = nil
46
+ @title = nil
47
+ @html_link_rel = {}
48
+ @html_link_rev = {}
49
+
50
+ @footnotes = []
51
+ @index = {}
52
+
53
+ # @use_old_anchor = nil
54
+ @use_old_anchor = true # MUST -> nil
55
+ @output_rbl = nil
56
+ super
57
+ end
58
+
59
+ def visit(tree)
60
+ prepare_labels(tree, "label-")
61
+ prepare_footnotes(tree)
62
+ tmp = super(tree)
63
+ make_rbl_file(@filename) if @output_rbl and @filename
64
+ tmp
65
+ end
66
+
67
+ def apply_to_DocumentElement(element, content)
68
+ ret = ""
69
+ ret << xml_decl + "\n"
70
+ ret << doctype_decl + "\n"
71
+ ret << html_open_tag + "\n"
72
+ ret << html_head + "\n"
73
+ ret << html_body(content) + "\n"
74
+ ret << "</html>\n"
75
+ ret
76
+ end
77
+
78
+ def document_title
79
+ return @title if @title
80
+ return @filename if @filename
81
+ return ARGF.filename if ARGF.filename != "-"
82
+ "Untitled"
83
+ end
84
+ private :document_title
85
+
86
+ def xml_decl
87
+ encoding = %[encoding="#{@charset}" ] if @charset
88
+ %|<?xml version="1.0" #{encoding}?>|
89
+ end
90
+ private :xml_decl
91
+
92
+ def doctype_decl
93
+ %|<!DOCTYPE html \n| +
94
+ %| PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"\n| +
95
+ %| "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">|
96
+ end
97
+ private :doctype_decl
98
+
99
+ def html_open_tag
100
+ lang_attr = %[ lang="#{@lang}" xml:lang="#{@lang}"] if @lang
101
+ %|<html xmlns="http://www.w3.org/1999/xhtml"#{lang_attr}>|
102
+ end
103
+ private :html_open_tag
104
+
105
+ def html_head
106
+ ret = %|<head>\n|
107
+ ret << html_title + "\n"
108
+ ret << html_content_type + "\n" if html_content_type
109
+ ret << link_to_css + "\n" if link_to_css
110
+ ret << forward_links + "\n" if forward_links
111
+ ret << backward_links + "\n" if backward_links
112
+ ret << %Q[</head>]
113
+ end
114
+ private :html_head
115
+
116
+ def html_title
117
+ "<title>#{document_title}</title>"
118
+ end
119
+ private :html_title
120
+
121
+ def html_content_type
122
+ if @charset
123
+ %Q[<meta http-equiv="Content-type" ] +
124
+ %Q[content="text/html; charset=#{@charset}" ] +
125
+ "/>"
126
+ end
127
+ end
128
+ private :html_content_type
129
+
130
+ def link_to_css
131
+ if @css
132
+ %|<link href="#{@css}" type="text/css" rel="stylesheet" | +
133
+ "/>" # for ruby-mode.el fontlock, it is separated into 2 lines.
134
+ end
135
+ end
136
+ private :link_to_css
137
+
138
+ def forward_links
139
+ return nil if @html_link_rel.empty?
140
+ rels = @html_link_rel.sort{|i, j| i[0] <=> j[0] }
141
+ (rels.collect do |rel, href|
142
+ %Q[<link href="#{href}" rel="#{rel}" />]
143
+ end).join("\n")
144
+ end
145
+ private :forward_links
146
+
147
+ def backward_links
148
+ return nil if @html_link_rev.empty?
149
+ revs = @html_link_rev.sort{|i, j| i[0] <=> j[0] }
150
+ (revs.collect do |rev, href|
151
+ %Q[<link href="#{href}" rev="#{rev}" />]
152
+ end).join("\n")
153
+ end
154
+ private :backward_links
155
+
156
+ def html_body(contents)
157
+ content = contents.join("\n")
158
+ foottext = make_foottext
159
+ %Q|<body>\n#{content}\n#{foottext}\n</body>|
160
+ end
161
+ private :html_body
162
+
163
+ def apply_to_Headline(element, title)
164
+ anchor = get_anchor(element)
165
+ label = hyphen_escape(element.label)
166
+ title = title.join("")
167
+ %Q[<h#{element.level}><a name="#{anchor}" id="#{anchor}">#{title}</a>] +
168
+ %Q[</h#{element.level}><!-- RDLabel: "#{label}" -->]
169
+ end
170
+
171
+ # RDVisitor#apply_to_Include
172
+
173
+ def apply_to_TextBlock(element, content)
174
+ content = content.join("")
175
+ if (is_this_textblock_only_one_block_of_parent_listitem?(element) or
176
+ is_this_textblock_only_one_block_other_than_sublists_in_parent_listitem?(element))
177
+ content.chomp
178
+ else
179
+ %Q[<p>#{content.chomp}</p>]
180
+ end
181
+ end
182
+
183
+ def is_this_textblock_only_one_block_of_parent_listitem?(element)
184
+ parent = element.parent
185
+ (parent.is_a?(ItemListItem) or
186
+ parent.is_a?(EnumListItem) or
187
+ parent.is_a?(DescListItem) or
188
+ parent.is_a?(MethodListItem)) and
189
+ consist_of_one_textblock?(parent)
190
+ end
191
+
192
+ def is_this_textblock_only_one_block_other_than_sublists_in_parent_listitem?(element)
193
+ parent = element.parent
194
+ (parent.is_a?(ItemListItem) or
195
+ parent.is_a?(EnumListItem) or
196
+ parent.is_a?(DescListItem) or
197
+ parent.is_a?(MethodListItem)) and
198
+ consist_of_one_textblock_and_sublists(element.parent)
199
+ end
200
+
201
+ def consist_of_one_textblock_and_sublists(element)
202
+ i = 0
203
+ element.each_child do |child|
204
+ if i == 0
205
+ return false unless child.is_a?(TextBlock)
206
+ else
207
+ return false unless child.is_a?(List)
208
+ end
209
+ i += 1
210
+ end
211
+ return true
212
+ end
213
+
214
+ def apply_to_Verbatim(element)
215
+ content = []
216
+ element.each_line do |i|
217
+ content.push(apply_to_String(i))
218
+ end
219
+ %Q[<pre>#{content.join("").chomp}</pre>]
220
+ end
221
+
222
+ def apply_to_ItemList(element, items)
223
+ %Q[<ul>\n#{items.join("\n").chomp}\n</ul>]
224
+ end
225
+
226
+ def apply_to_EnumList(element, items)
227
+ %Q[<ol>\n#{items.join("\n").chomp}\n</ol>]
228
+ end
229
+
230
+ def apply_to_DescList(element, items)
231
+ %Q[<dl>\n#{items.join("\n").chomp}\n</dl>]
232
+ end
233
+
234
+ def apply_to_MethodList(element, items)
235
+ %Q[<dl>\n#{items.join("\n").chomp}\n</dl>]
236
+ end
237
+
238
+ def apply_to_ItemListItem(element, content)
239
+ %Q[<li>#{content.join("\n").chomp}</li>]
240
+ end
241
+
242
+ def apply_to_EnumListItem(element, content)
243
+ %Q[<li>#{content.join("\n").chomp}</li>]
244
+ end
245
+
246
+ def consist_of_one_textblock?(listitem)
247
+ listitem.children.size == 1 and listitem.children[0].is_a?(TextBlock)
248
+ end
249
+ private :consist_of_one_textblock?
250
+
251
+ def apply_to_DescListItem(element, term, description)
252
+ anchor = get_anchor(element.term)
253
+ label = hyphen_escape(element.label)
254
+ term = term.join("")
255
+ if description.empty?
256
+ %Q[<dt><a name="#{anchor}" id="#{anchor}">#{term}</a></dt>] +
257
+ %Q[<!-- RDLabel: "#{label}" -->]
258
+ else
259
+ %Q[<dt><a name="#{anchor}" id="#{anchor}">#{term}</a></dt>] +
260
+ %Q[<!-- RDLabel: "#{label}" -->\n] +
261
+ %Q[<dd>\n#{description.join("\n").chomp}\n</dd>]
262
+ end
263
+ end
264
+
265
+ def apply_to_MethodListItem(element, term, description)
266
+ term = parse_method(term) # maybe: term -> element.term
267
+ anchor = get_anchor(element.term)
268
+ label = hyphen_escape(element.label)
269
+ if description.empty?
270
+ %Q[<dt><a name="#{anchor}" id="#{anchor}"><code>#{term}] +
271
+ %Q[</code></a></dt><!-- RDLabel: "#{label}" -->]
272
+ else
273
+ %Q[<dt><a name="#{anchor}" id="#{anchor}"><code>#{term}] +
274
+ %Q[</code></a></dt><!-- RDLabel: "#{label}" -->\n] +
275
+ %Q[<dd>\n#{description.join("\n")}</dd>]
276
+ end
277
+ end
278
+
279
+ def apply_to_StringElement(element)
280
+ apply_to_String(element.content)
281
+ end
282
+
283
+ def apply_to_Emphasis(element, content)
284
+ %Q[<em>#{content.join("")}</em>]
285
+ end
286
+
287
+ def apply_to_Code(element, content)
288
+ %Q[<code>#{content.join("")}</code>]
289
+ end
290
+
291
+ def apply_to_Var(element, content)
292
+ %Q[<var>#{content.join("")}</var>]
293
+ end
294
+
295
+ def apply_to_Keyboard(element, content)
296
+ %Q[<kbd>#{content.join("")}</kbd>]
297
+ end
298
+
299
+ def apply_to_Index(element, content)
300
+ tmp = []
301
+ element.each do |i|
302
+ tmp.push(i) if i.is_a?(String)
303
+ end
304
+ key = meta_char_escape(tmp.join(""))
305
+ if @index.has_key?(key)
306
+ # warning?
307
+ %Q[<!-- Index, but conflict -->#{content.join("")}<!-- Index end -->]
308
+ else
309
+ num = @index[key] = @index.size
310
+ anchor = a_name("index", num)
311
+ %Q[<a name="#{anchor}" id="#{anchor}">#{content.join("")}</a>]
312
+ end
313
+ end
314
+
315
+ def apply_to_Reference_with_RDLabel(element, content)
316
+ if element.label.filename
317
+ apply_to_RefToOtherFile(element, content)
318
+ else
319
+ apply_to_RefToElement(element, content)
320
+ end
321
+ end
322
+
323
+ def apply_to_Reference_with_URL(element, content)
324
+ %Q[<a href="#{meta_char_escape(element.label.url)}">] +
325
+ %Q[#{content.join("")}</a>]
326
+ end
327
+
328
+ def apply_to_RefToElement(element, content)
329
+ content = content.join("")
330
+ if anchor = refer(element)
331
+ content = content.sub(/^function#/, "")
332
+ %Q[<a href="\##{anchor}">#{content}</a>]
333
+ else
334
+ # warning?
335
+ label = hyphen_escape(element.to_label)
336
+ %Q[<!-- Reference, RDLabel "#{label}" doesn't exist -->] +
337
+ %Q[<em class="label-not-found">#{content}</em><!-- Reference end -->]
338
+ #'
339
+ end
340
+ end
341
+
342
+ def apply_to_RefToOtherFile(element, content)
343
+ content = content.join("")
344
+ filename = element.label.filename.sub(/\.(rd|rb)(\.\w+)?$/, "." +
345
+ OUTPUT_SUFFIX)
346
+ anchor = refer_external(element)
347
+ if anchor
348
+ %Q[<a href="#{filename}\##{anchor}">#{content}</a>]
349
+ else
350
+ %Q[<a href="#{filename}">#{content}</a>]
351
+ end
352
+ end
353
+
354
+ def apply_to_Footnote(element, content)
355
+ num = get_footnote_num(element)
356
+ raise ArgumentError, "[BUG?] #{element} is not registered." unless num
357
+
358
+ add_foottext(num, content)
359
+ anchor = a_name("footmark", num)
360
+ href = a_name("foottext", num)
361
+ %Q|<a name="#{anchor}" id="#{anchor}" | +
362
+ %Q|href="##{href}"><sup><small>| +
363
+ %Q|*#{num}</small></sup></a>|
364
+ end
365
+
366
+ def get_footnote_num(fn)
367
+ raise ArgumentError, "#{fn} must be Footnote." unless fn.is_a? Footnote
368
+ i = @footnotes.index(fn)
369
+ if i
370
+ i + 1
371
+ else
372
+ nil
373
+ end
374
+ end
375
+
376
+ def prepare_footnotes(tree)
377
+ @footnotes = tree.find_all{|i| i.is_a? Footnote }
378
+ @foottexts = []
379
+ end
380
+ private :prepare_footnotes
381
+
382
+ def apply_to_Foottext(element, content)
383
+ num = get_footnote_num(element)
384
+ raise ArgumentError, "[BUG] #{element} isn't registered." unless num
385
+ anchor = a_name("foottext", num)
386
+ href = a_name("footmark", num)
387
+ content = content.join("")
388
+ %|<a name="#{anchor}" id="#{anchor}" href="##{href}">|+
389
+ %|<sup><small>*#{num}</small></sup></a>| +
390
+ %|<small>#{content}</small><br />|
391
+ end
392
+
393
+ def add_foottext(num, foottext)
394
+ raise ArgumentError, "[BUG] footnote ##{num} isn't here." unless
395
+ footnotes[num - 1]
396
+ @foottexts[num - 1] = foottext
397
+ end
398
+
399
+ def apply_to_Verb(element)
400
+ content = apply_to_String(element.content)
401
+ %Q[#{content}]
402
+ end
403
+
404
+ def sp2nbsp(str)
405
+ str.gsub(/\s/, "&nbsp;")
406
+ end
407
+ private :sp2nbsp
408
+
409
+ def apply_to_String(element)
410
+ meta_char_escape(element)
411
+ end
412
+
413
+ def parse_method(method)
414
+ klass, kind, method, args = MethodParse.analize_method(method)
415
+
416
+ if kind == :function
417
+ klass = kind = nil
418
+ else
419
+ kind = MethodParse.kind2str(kind)
420
+ end
421
+
422
+ args.gsub!(/&?\w+;?/){ |m|
423
+ if /&\w+;/ =~ m then m else '<var>'+m+'</var>' end }
424
+
425
+ case method
426
+ when "self"
427
+ klass, kind, method, args = MethodParse.analize_method(args)
428
+ "#{klass}#{kind}<var>self</var> #{method}#{args}"
429
+ when "[]"
430
+ args.strip!
431
+ args.sub!(/^\((.*)\)$/, '\\1')
432
+ "#{klass}#{kind}[#{args}]"
433
+ when "[]="
434
+ args.tr!(' ', '')
435
+ args.sub!(/^\((.*)\)$/, '\\1')
436
+ ary = args.split(/,/)
437
+
438
+ case ary.length
439
+ when 1
440
+ val = '<var>val</var>'
441
+ when 2
442
+ args, val = *ary
443
+ when 3
444
+ args, val = ary[0, 2].join(', '), ary[2]
445
+ end
446
+
447
+ "#{klass}#{kind}[#{args}] = #{val}"
448
+ else
449
+ "#{klass}#{kind}#{method}#{args}"
450
+ end
451
+ end
452
+ private :parse_method
453
+
454
+ def meta_char_escape(str)
455
+ str.gsub(/[<>&]/) {
456
+ METACHAR[$&]
457
+ }
458
+ end
459
+ private :meta_char_escape
460
+
461
+ def hyphen_escape(str)
462
+ str.gsub(/--/, "&shy;&shy;")
463
+ end
464
+
465
+ def make_foottext
466
+ return nil if foottexts.empty?
467
+ content = []
468
+ foottexts.each_with_index do |ft, num|
469
+ content.push(apply_to_Foottext(footnotes[num], ft))
470
+ end
471
+ %|<hr />\n<p class="foottext">\n#{content.join("\n")}\n</p>|
472
+ end
473
+ private :make_foottext
474
+
475
+ def a_name(prefix, num)
476
+ "#{prefix}-#{num}"
477
+ end
478
+ private :a_name
479
+ end # RD2HTMLVisitor
480
+ end # RD
481
+
482
+ $Visitor_Class = RD::RD2HTMLVisitor
483
+ $RD2_Sub_OptionParser = "rd/rd2html-opt"
484
+
485
+ =begin
486
+ == script info.
487
+ RD to HTML translate library for rdfmt.rb
488
+ $Id: rd2html-lib.rb,v 1.53 2003/03/08 12:45:08 tosh Exp $
489
+
490
+ =end