review 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. data/COPYING +515 -0
  2. data/ChangeLog +1278 -0
  3. data/README.rdoc +21 -0
  4. data/Rakefile +42 -0
  5. data/VERSION +1 -0
  6. data/bin/review-check +190 -0
  7. data/bin/review-checkdep +63 -0
  8. data/bin/review-compile +165 -0
  9. data/bin/review-epubmaker +525 -0
  10. data/bin/review-index +108 -0
  11. data/bin/review-preproc +140 -0
  12. data/bin/review-validate +51 -0
  13. data/bin/review-vol +106 -0
  14. data/doc/format.re +486 -0
  15. data/doc/format.txt +434 -0
  16. data/doc/format_idg.txt +194 -0
  17. data/doc/format_sjis.txt +313 -0
  18. data/doc/sample.css +91 -0
  19. data/doc/sample.yaml +46 -0
  20. data/lib/lineinput.rb +155 -0
  21. data/lib/review/book.rb +580 -0
  22. data/lib/review/builder.rb +274 -0
  23. data/lib/review/compat.rb +22 -0
  24. data/lib/review/compiler.rb +483 -0
  25. data/lib/review/epubbuilder.rb +692 -0
  26. data/lib/review/ewbbuilder.rb +382 -0
  27. data/lib/review/exception.rb +21 -0
  28. data/lib/review/htmlbuilder.rb +370 -0
  29. data/lib/review/htmllayout.rb +19 -0
  30. data/lib/review/htmlutils.rb +27 -0
  31. data/lib/review/idgxmlbuilder.rb +1078 -0
  32. data/lib/review/index.rb +224 -0
  33. data/lib/review/latexbuilder.rb +420 -0
  34. data/lib/review/latexindex.rb +35 -0
  35. data/lib/review/latexutils.rb +52 -0
  36. data/lib/review/preprocessor.rb +520 -0
  37. data/lib/review/textutils.rb +19 -0
  38. data/lib/review/tocparser.rb +333 -0
  39. data/lib/review/tocprinter.rb +220 -0
  40. data/lib/review/topbuilder.rb +572 -0
  41. data/lib/review/unfold.rb +138 -0
  42. data/lib/review/volume.rb +66 -0
  43. data/lib/review.rb +4 -0
  44. data/review.gemspec +93 -0
  45. data/setup.rb +1587 -0
  46. data/test/test_epubbuilder.rb +73 -0
  47. data/test/test_helper.rb +2 -0
  48. data/test/test_htmlbuilder.rb +42 -0
  49. data/test/test_latexbuilder.rb +74 -0
  50. metadata +122 -0
@@ -0,0 +1,19 @@
1
+ # Copyright (c) 2009 Narihiro Nakamura <authornari@gmail.com>
2
+ require 'erb'
3
+
4
+ class HTMLLayout
5
+ def initialize(src, title, template)
6
+ @body = src
7
+ @title = title
8
+ @template = template
9
+ end
10
+ attr_reader :body, :title
11
+
12
+ def result
13
+ if File.exist?(@template)
14
+ return ERB.new(IO.read(@template)).result(binding)
15
+ else
16
+ return @src
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ #
2
+ # $Id: htmlutils.rb 2227 2006-05-13 00:09:08Z aamine $
3
+ #
4
+ # Copyright (c) 2002-2006 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute or modify this program under the terms of
8
+ # the GNU LGPL, Lesser General Public License version 2.1.
9
+ #
10
+
11
+ module ReVIEW
12
+
13
+ module HTMLUtils
14
+ ESC = {
15
+ '&' => '&amp;',
16
+ '<' => '&lt;',
17
+ '>' => '&gt;',
18
+ '"' => '&quot;'
19
+ }
20
+
21
+ def escape_html(str)
22
+ t = ESC
23
+ str.gsub(/[&"<>]/) {|c| t[c] }
24
+ end
25
+ end
26
+
27
+ end # module ReVIEW
@@ -0,0 +1,1078 @@
1
+ #
2
+ # Copyright (c) 2002-2007 Minero Aoki
3
+ # 2008-2010 Minero Aoki, Kenshi Muto
4
+ #
5
+ # This program is free software.
6
+ # You can distribute or modify this program under the terms of
7
+ # the GNU LGPL, Lesser General Public License version 2.1.
8
+ #
9
+
10
+ require 'review/builder'
11
+ require 'review/htmlutils'
12
+ require 'review/textutils'
13
+ require 'nkf'
14
+
15
+ module ReVIEW
16
+
17
+ class IDGXMLBuilder < Builder
18
+
19
+ include TextUtils
20
+ include HTMLUtils
21
+
22
+ [:i, :tt, :ttbold, :tti, :idx, :hidx, :dtp, :sup, :sub, :hint, :raw, :maru, :keytop, :labelref, :ref, :pageref, :u, :icon, :balloon, :uchar].each {|e|
23
+ Compiler.definline(e)
24
+ }
25
+ Compiler.defsingle(:dtp, 1)
26
+ Compiler.defsingle(:indepimage, 1)
27
+
28
+ Compiler.defblock(:insn, 0..1)
29
+ Compiler.defblock(:memo, 0..1)
30
+ Compiler.defblock(:tip, 0..1)
31
+ Compiler.defblock(:info, 0..1)
32
+ Compiler.defblock(:planning, 0..1)
33
+ Compiler.defblock(:best, 0..1)
34
+ Compiler.defblock(:important, 0..1)
35
+ Compiler.defblock(:security, 0..1)
36
+ Compiler.defblock(:caution, 0..1)
37
+ Compiler.defblock(:notice, 0..1)
38
+ Compiler.defblock(:point, 0..1)
39
+ Compiler.defblock(:shoot, 0..1)
40
+ Compiler.defblock(:reference, 0)
41
+ Compiler.defblock(:term, 0)
42
+ Compiler.defblock(:link, 0..1)
43
+ Compiler.defblock(:practice, 0)
44
+ Compiler.defblock(:box, 0..1)
45
+ Compiler.defblock(:expert, 0)
46
+ Compiler.defblock(:lead, 0)
47
+ Compiler.defblock(:rawblock, 0)
48
+
49
+ def extname
50
+ '.xml'
51
+ end
52
+
53
+ def builder_init(no_error = false)
54
+ @no_error = no_error
55
+ end
56
+ private :builder_init
57
+
58
+ def setParameter(param)
59
+ @param = param
60
+ alias puts print unless @param["nolf"].nil?
61
+ end
62
+
63
+ def builder_init_file
64
+ @warns = []
65
+ @errors = []
66
+ @section = 0
67
+ @subsection = 0
68
+ @subsubsection = 0
69
+ @subsubsubsection = 0
70
+ @noindent = nil
71
+ @rootelement = "doc"
72
+ @secttags = nil
73
+ @tsize = nil
74
+
75
+ print %Q(<?xml version="1.0" encoding="UTF-8"?>\n)
76
+ print %Q(<#{@rootelement} xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/">)
77
+ end
78
+ private :builder_init_file
79
+
80
+ def result
81
+ s = ""
82
+ unless @secttags.nil?
83
+ s += "</sect4>" if @subsubsubsection > 0
84
+ s += "</sect3>" if @subsubsection > 0
85
+ s += "</sect2>" if @subsection > 0
86
+ s += "</sect>" if @section > 0
87
+ s += "</chapter>" if @chapter.number > 0
88
+ end
89
+ messages() + @output.string + s + "</#{@rootelement}>\n"
90
+ end
91
+
92
+ def warn(msg)
93
+ if @no_error
94
+ @warns.push [@location.filename, @location.lineno, msg]
95
+ puts "----WARNING: #{escape_html(msg)}----"
96
+ else
97
+ $stderr.puts "#{@location}: warning: #{msg}"
98
+ end
99
+ end
100
+
101
+ def error(msg)
102
+ if @no_error
103
+ @errors.push [@location.filename, @location.lineno, msg]
104
+ puts "----ERROR: #{escape_html(msg)}----"
105
+ else
106
+ $stderr.puts "#{@location}: error: #{msg}"
107
+ end
108
+ end
109
+
110
+ def messages
111
+ error_messages() + warning_messages()
112
+ end
113
+
114
+ def error_messages
115
+ return '' if @errors.empty?
116
+ "<h2>Syntax Errors</h2>\n" +
117
+ "<ul>\n" +
118
+ @errors.map {|file, line, msg|
119
+ "<li>#{escape_html(file)}:#{line}: #{escape_html(msg.to_s)}</li>\n"
120
+ }.join('') +
121
+ "</ul>\n"
122
+ end
123
+
124
+ def warning_messages
125
+ return '' if @warns.empty?
126
+ "<h2>Warnings</h2>\n" +
127
+ "<ul>\n" +
128
+ @warns.map {|file, line, msg|
129
+ "<li>#{escape_html(file)}:#{line}: #{escape_html(msg)}</li>\n"
130
+ }.join('') +
131
+ "</ul>\n"
132
+ end
133
+
134
+ def headline(level, label, caption)
135
+ prefix = ""
136
+ case level
137
+ when 1
138
+ unless @secttags.nil?
139
+ print "</sect4>" if @subsubsubsection > 0
140
+ print "</sect3>" if @subsubsection > 0
141
+ print "</sect2>" if @subsection > 0
142
+ print "</sect>" if @section > 0
143
+ end
144
+
145
+ print %Q(<chapter id="chap:#{@chapter.number}">) unless @secttags.nil?
146
+ if @chapter.number.to_s =~ /\A\d+$/
147
+ prefix = "第#{@chapter.number}章 "
148
+ elsif !@chapter.number.nil? && !@chapter.number.to_s.empty?
149
+ prefix = "#{@chapter.number} "
150
+ end
151
+ @section = 0
152
+ @subsection = 0
153
+ @subsubsection = 0
154
+ @subsubsubsection = 0
155
+ when 2
156
+ unless @secttags.nil?
157
+ print "</sect4>" if @subsubsubsection > 0
158
+ print "</sect3>" if @subsubsection > 0
159
+ print "</sect2>" if @subsection > 0
160
+ print "</sect>" if @section > 0
161
+ end
162
+ @section += 1
163
+ print %Q(<sect id="sect:#{@chapter.number}.#{@section}">) unless @secttags.nil?
164
+
165
+ prefix = (!@chapter.number.nil? && !@chapter.number.to_s.empty?) ? "#{@chapter.number}.#{@section} " : ""
166
+
167
+ @subsection = 0
168
+ @subsubsection = 0
169
+ @subsubsubsection = 0
170
+ when 3
171
+ unless @secttags.nil?
172
+ print "</sect4>" if @subsubsubsection > 0
173
+ print "</sect3>" if @subsubsection > 0
174
+ print "</sect2>" if @subsection > 0
175
+ end
176
+
177
+ @subsection += 1
178
+ print %Q(<sect2 id="sect:#{@chapter.number}.#{@section}.#{@subsection}">) unless @secttags.nil?
179
+ prefix = (!@chapter.number.nil? && !@chapter.number.to_s.empty?) ? "#{@chapter.number}.#{@section}.#{@subsection} " : ""
180
+
181
+ @subsubsection = 0
182
+ @subsubsubsection = 0
183
+ when 4
184
+ unless @secttags.nil?
185
+ print "</sect4>" if @subsubsubsection > 0
186
+ print "</sect3>" if @subsubsection > 0
187
+ end
188
+
189
+ @subsubsection += 1
190
+ print %Q(<sect3 id="sect:#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection}">) unless @secttags.nil?
191
+ prefix = (!@chapter.number.nil? && !@chapter.number.to_s.empty?) ? "#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection} " : ""
192
+
193
+ @subsubsubsection = 0
194
+ when 5
195
+ unless @secttags.nil?
196
+ print "</sect4>" if @subsubsubsection > 0
197
+ end
198
+
199
+ @subsubsubsection += 1
200
+ print %Q(<sect4 id="sect:#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection}.#{@subsubsubsection}">) unless @secttags.nil?
201
+ prefix = (!@chapter.number.nil? && !@chapter.number.to_s.empty?) ? "#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection}.#{@subsubsubsection} " : ""
202
+ else
203
+ raise "caption level too deep or unsupported: #{level}"
204
+ end
205
+
206
+ prefix = "" if (level.to_i > @param["secnolevel"])
207
+ label = label.nil? ? "" : " id=\"#{label}\""
208
+ puts %Q(<title#{label} aid:pstyle="h#{level}">#{prefix}#{escape_html(caption)}</title><?dtp level="#{level}" section="#{prefix}#{escape_html(caption)}"?>)
209
+ end
210
+
211
+ def ul_begin
212
+ puts '<ul>'
213
+ end
214
+
215
+ def ul_item(lines)
216
+ puts %Q(<li aid:pstyle="ul-item">#{lines.join("\n").chomp}</li>)
217
+ end
218
+
219
+ def choice_single_begin
220
+ puts "<choice type='single'>"
221
+ end
222
+
223
+ def choice_multi_begin
224
+ puts "<choice type='multi'>"
225
+ end
226
+
227
+ def choice_single_end
228
+ puts "</choice>"
229
+ end
230
+
231
+ def choice_multi_end
232
+ puts "</choice>"
233
+ end
234
+
235
+ def ul_end
236
+ puts '</ul>'
237
+ end
238
+
239
+ def ol_begin
240
+ puts '<ol>'
241
+ end
242
+
243
+ def ol_item(lines, num)
244
+ puts %Q(<li aid:pstyle="ol-item" num="#{num}">#{lines.join("\n").chomp}</li>)
245
+ end
246
+
247
+ def ol_end
248
+ puts '</ol>'
249
+ end
250
+
251
+ def dl_begin
252
+ puts '<dl>'
253
+ end
254
+
255
+ def dt(line)
256
+ puts "<dt>#{line}</dt>"
257
+ end
258
+
259
+ def dd(lines)
260
+ puts "<dd>#{lines.join("\n").chomp}</dd>"
261
+ end
262
+
263
+ def dl_end
264
+ puts '</dl>'
265
+ end
266
+
267
+ def paragraph(lines)
268
+ if @noindent.nil?
269
+ if lines[0] =~ /^(\t+)/
270
+ puts %Q(<p inlist="#{$1.size}">#{lines.join('').sub(/^\t+/, "")}</p>)
271
+ else
272
+ puts "<p>#{lines.join('')}</p>"
273
+ end
274
+ else
275
+ puts %Q(<p aid:pstyle="noindent" noindent='1'>#{lines.join('')}</p>)
276
+ @noindent = nil
277
+ end
278
+ end
279
+
280
+ def read(lines)
281
+ puts %Q[<p aid:pstyle="lead">#{lines.join('')}</p>]
282
+ end
283
+
284
+ def lead(lines)
285
+ read(lines)
286
+ end
287
+
288
+ def inline_list(id)
289
+ if !@chapter.number.nil? && !@chapter.number.to_s.empty?
290
+ "<span type='list'>リスト#{@chapter.number}.#{@chapter.list(id).number}</span>"
291
+ else
292
+ "<span type='list'>リスト#{@chapter.list(id).number}</span>"
293
+ end
294
+ end
295
+
296
+ def list_header(id, caption)
297
+ if !@chapter.number.nil? && !@chapter.number.to_s.empty?
298
+ puts %Q[<codelist>]
299
+ puts %Q[<caption>リスト#{@chapter.number}.#{@chapter.list(id).number} #{escape_html(caption)}</caption>]
300
+ else
301
+ puts %Q[<codelist>]
302
+ puts %Q[<caption>リスト#{@chapter.list(id).number} #{escape_html(caption)}</caption>]
303
+ end
304
+ end
305
+
306
+ def list_body(lines)
307
+ print %Q(<pre>)
308
+ lines.each do |line|
309
+ print detab(line)
310
+ print "\n"
311
+ end
312
+ puts "</pre></codelist>"
313
+ end
314
+
315
+ def emlist(lines, caption = nil)
316
+ quotedlist lines, 'emlist', caption
317
+ end
318
+
319
+ def emlistnum(lines, caption = nil)
320
+ _lines = []
321
+ lines.each_with_index do |line, i|
322
+ _lines << detab("<span type='lineno'>" + (i+1).to_s.rjust(2) + ": </span>" + line)
323
+ end
324
+ quotedlist _lines, 'emlist', caption
325
+ end
326
+
327
+ def listnum_body(lines)
328
+ print %Q(<pre>)
329
+ lines.each_with_index do |line, i|
330
+ print detab("<span type='lineno'>" + (i+1).to_s.rjust(2) + ": </span>" + line)
331
+ print "\n"
332
+ end
333
+ puts "</pre></codelist>"
334
+ end
335
+
336
+ def cmd(lines, caption = nil)
337
+ quotedlist lines, 'cmd', caption
338
+ end
339
+
340
+ def quotedlist(lines, css_class, caption)
341
+ print %Q[<list type='#{css_class}'>]
342
+ puts "<caption aid:pstyle='#{css_class}-title'>#{escape_html(caption)}</caption>" unless caption.nil?
343
+ print %Q[<pre>]
344
+ no = 1
345
+ lines.each do |line|
346
+ unless @param["listinfo"].nil?
347
+ print "<listinfo line=\"#{no}\""
348
+ print " begin=\"1\"" if no == 1
349
+ print " end=\"#{no}\"" if no == lines.size
350
+ print ">"
351
+ end
352
+ print detab(line)
353
+ print "\n"
354
+ print "</listinfo>" unless @param["listinfo"].nil?
355
+ no += 1
356
+ end
357
+ puts '</pre></list>'
358
+ end
359
+ private :quotedlist
360
+
361
+ def quote(lines)
362
+ puts "<quote>#{lines.join("\n")}</quote>"
363
+ end
364
+
365
+ def inline_table(id)
366
+ if !@chapter.number.nil? && !@chapter.number.to_s.empty?
367
+ "<span type='table'>表#{@chapter.number}.#{@chapter.table(id).number}</span>"
368
+ else
369
+ "<span type='table'>表#{@chapter.table(id).number}</span>"
370
+ end
371
+ end
372
+
373
+ def inline_img(id)
374
+ if !@chapter.number.nil? && !@chapter.number.to_s.empty?
375
+ "<span type='image'>図#{@chapter.number}.#{@chapter.image(id).number}</span>"
376
+ else
377
+ "<span type='image'>図#{@chapter.image(id).number}</span>"
378
+ end
379
+ end
380
+
381
+ def image_image(id, metric, caption)
382
+ puts "<img>"
383
+ puts %Q[<Image href="file://#{@chapter.image(id).path.sub(/\A.\//, "")}" />]
384
+ image_header id, caption
385
+ puts "</img>"
386
+ end
387
+
388
+ def image_dummy(id, caption, lines)
389
+ if @param["subdirmode"].nil?
390
+ warn "image file not exist: images/#{@chapter.id}-#{id}.eps" unless File.exist?("images/#{@chapter.id}-#{id}.eps")
391
+ else
392
+ warn "image file not exist: images/#{@chapter.id}/#{id}.eps" unless File.exist?("images/#{@chapter.id}/#{id}.eps")
393
+ end
394
+ puts "<img>"
395
+ print %Q[<pre aid:pstyle="dummyimage">]
396
+ lines.each do |line|
397
+ print detab(line)
398
+ print "\n"
399
+ end
400
+ print %Q[</pre>]
401
+ image_header id, caption
402
+ puts "</img>"
403
+ end
404
+
405
+ def image_header(id, caption)
406
+ if !@chapter.number.nil? && !@chapter.number.to_s.empty?
407
+ puts %Q[<caption>図#{@chapter.number}.#{@chapter.image(id).number} #{escape_html(caption)}</caption>]
408
+ else
409
+ puts %Q[<caption>図#{@chapter.image(id).number} #{escape_html(caption)}</caption>]
410
+ end
411
+ end
412
+
413
+ def table(lines, id = nil, caption = nil)
414
+ # puts %Q(<表 xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/" aid:table="table">)
415
+ tablewidth = nil
416
+ col = 0
417
+ unless @param["tableopt"].nil?
418
+ tablewidth = @param["tableopt"].split(",")[0].to_f / 0.351 # mm -> pt
419
+ end
420
+ puts "<table>"
421
+ rows = []
422
+ sepidx = nil
423
+ lines.each_with_index do |line, idx|
424
+ if /\A[\=\-]{12}/ =~ line
425
+ # just ignore
426
+ #error "too many table separator" if sepidx
427
+ sepidx ||= idx
428
+ next
429
+ end
430
+ if tablewidth.nil?
431
+ rows.push(line.gsub(/\t\.\t/, "\t\t").gsub(/\t\.\.\t/, "\t.\t").gsub(/\t\.\Z/, "\t").gsub(/\t\.\.\Z/, "\t.").gsub(/\A\./, ""))
432
+ else
433
+ rows.push(line.gsub(/\t\.\t/, "\tDUMMYCELLSPLITTER\t").gsub(/\t\.\.\t/, "\t.\t").gsub(/\t\.\Z/, "\tDUMMYCELLSPLITTER").gsub(/\t\.\.\Z/, "\t.").gsub(/\A\./, ""))
434
+ end
435
+ _col = rows[rows.length - 1].split(/\t/).length
436
+ col = _col if _col > col
437
+ end
438
+
439
+ cellwidth = []
440
+ unless tablewidth.nil?
441
+ if @tsize.nil?
442
+ col.times {|n|
443
+ cellwidth[n] = tablewidth / col
444
+ }
445
+ else
446
+ cellwidth = @tsize.split(/\s*,\s*/)
447
+ totallength = 0
448
+ cellwidth.size.times {|n|
449
+ cellwidth[n] = cellwidth[n].to_f / 0.351 # mm->pt
450
+ totallength = totallength + cellwidth[n]
451
+ warn "total length exceeds limit for table: #{id}" if totallength > tablewidth
452
+ }
453
+ if cellwidth.size < col
454
+ cw = (tablewidth - totallength) / (col - cellwidth.size)
455
+ warn "auto cell sizing exceeds limit for table: #{id}" if cw <= 0
456
+ for i in cellwidth.size..(col - 1)
457
+ cellwidth[i] = cw
458
+ end
459
+ end
460
+ end
461
+ end
462
+
463
+ begin
464
+ table_header id, caption unless caption.nil?
465
+ rescue KeyError => err
466
+ error "no such table: #{id}"
467
+ end
468
+ return if rows.empty?
469
+
470
+ if tablewidth.nil?
471
+ print "<tbody>"
472
+ else
473
+ print "<tbody xmlns:aid5=\"http://ns.adobe.com/AdobeInDesign/5.0/\" aid:table=\"table\" aid:trows=\"#{rows.length}\" aid:tcols=\"#{col}\">"
474
+ end
475
+
476
+ if sepidx
477
+ sepidx.times do
478
+ if tablewidth.nil?
479
+ puts "<tr type=\"header\">" + rows.shift + "</tr>"
480
+ else
481
+ i = 0
482
+ rows.shift.split(/\t/).each {|cell|
483
+ print "<td aid:table=\"cell\" aid:theader=\"1\" aid:crows=\"1\" aid:ccols=\"1\" aid:ccolwidth=\"#{cellwidth[i]}\">#{cell.sub("DUMMYCELLSPLITTER", "")}</td>"
484
+ i = i + 1
485
+ }
486
+ end
487
+ end
488
+
489
+ if tablewidth.nil?
490
+ lastline = rows.pop
491
+ rows.each do |row|
492
+ puts "<tr>" + row + "</tr>"
493
+ end
494
+ puts "<tr type=\"lastline\">" + lastline + "</tr>" unless lastline.nil?
495
+ else
496
+ rows.each do |row|
497
+ i = 0
498
+ row.split(/\t/).each {|cell|
499
+ print "<td aid:table=\"cell\" aid:crows=\"1\" aid:ccols=\"1\" aid:ccolwidth=\"#{cellwidth[i]}\">#{cell.sub("DUMMYCELLSPLITTER", "")}</td>"
500
+ i = i + 1
501
+ }
502
+ end
503
+ end
504
+ else
505
+ if tablewidth.nil?
506
+ lastline = rows.pop
507
+ rows.each do |row|
508
+ puts "<tr>" + row + "</tr>"
509
+ end
510
+ puts "<tr type=\"lastline\">" + lastline + "</tr>" unless lastline.nil?
511
+ else
512
+ rows.each do |row|
513
+ i = 0
514
+ row.split(/\t/).each {|cell|
515
+ print "<td aid:table=\"cell\" aid:crows=\"1\" aid:ccols=\"1\" aid:ccolwidth=\"#{cellwidth[i]}\">#{cell.sub("DUMMYCELLSPLITTER", "")}</td>"
516
+ i = i + 1
517
+ }
518
+ end
519
+ end
520
+ end
521
+ print "</tbody>"
522
+ puts "</table>"
523
+ @tsize = nil
524
+ end
525
+
526
+ def table_header(id, caption)
527
+ if !@chapter.number.nil? && !@chapter.number.to_s.empty?
528
+ puts %Q[<caption>表#{@chapter.number}.#{@chapter.table(id).number} #{escape_html(caption)}</caption>]
529
+ else
530
+ puts %Q[<caption>表#{@chapter.table(id).number} #{escape_html(caption)}</caption>]
531
+ end
532
+ end
533
+
534
+ def table_begin(ncols)
535
+ # aid:trows="" aid:tcols="" widths="列1の幅, 列2の幅, ..."をdtp命令で入れておく
536
+ # puts %Q(<表 xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/" aid:table="table">)
537
+ end
538
+
539
+ def tr(rows)
540
+ # FIXME
541
+ puts "<tr>" + rows.join("\t") + "</tr>"
542
+ end
543
+
544
+ def th(str)
545
+ # FIXME aid:ccolwidth=""
546
+ # FIXME strが2回エスケープされている
547
+ # %Q(<セル aid:table="cell" aid:theader="" aid:crows="1" aid:ccols="1">#{str}</セル>)
548
+ %Q(<?dtp tablerow header?>#{str})
549
+ end
550
+
551
+ def td(str)
552
+ # FIXME aid:ccolwidth=""
553
+ # FIXME strが2回エスケープされている
554
+ # %Q(<セル aid:table="cell" aid:crows="1" aid:ccols="1">#{str}</セル>)
555
+ str
556
+ end
557
+
558
+ def table_end
559
+ # puts '</表>'
560
+ print "<?dtp tablerow last?>"
561
+ end
562
+
563
+ def comment(str)
564
+ print %Q(<!-- [Comment] #{escape_html(str)} -->)
565
+ end
566
+
567
+ def footnote(id, str)
568
+ # FIXME: inline_fnと合わせて処理必要。2パースの処理をすべきか
569
+ # puts %Q(<footnote id="#{id}" no="#{@chapter.footnote(id).number}">#{compile_inline(str)}</footnote>)
570
+ end
571
+
572
+ def inline_fn(id)
573
+ %Q(<footnote>#{compile_inline(@chapter.footnote(id).content.strip)}</footnote>)
574
+ end
575
+
576
+ def compile_ruby(base, ruby)
577
+ %Q(<GroupRuby><aid:ruby xmlns:aid="http://ns.adobe.com/AdobeInDesign/3.0/"><aid:rb>#{escape_html(base.sub(/\A\s+/, "").sub(/\s+$/, ""))}</aid:rb><aid:rt>#{escape_html(ruby.sub(/\A\s+/, "").sub(/\s+$/, ""))}</aid:rt></aid:ruby></GroupRuby>)
578
+ end
579
+
580
+ def compile_kw(word, alt)
581
+ '<keyword>' +
582
+ if alt
583
+ #then escape_html(word + sprintf(@locale[:parens], alt.strip))
584
+ then escape_html(word + "(#{alt.strip})")
585
+ else escape_html(word)
586
+ end +
587
+ '</keyword>' +
588
+ %Q(<index value="#{escape_html(word)}" />) +
589
+ if alt
590
+ alt.split(/\s*,\s*/).collect! {|e| %Q(<index value="#{escape_html(e.strip)}" />) }.join
591
+ else
592
+ ""
593
+ end
594
+ end
595
+
596
+ def compile_href(url, label)
597
+ %Q(<a linkurl='#{url}'>#{label.nil? ? url : label}</a>)
598
+ end
599
+
600
+ def inline_sup(str)
601
+ %Q(<sup>#{escape_html(str)}</sup>)
602
+ end
603
+
604
+ def inline_sub(str)
605
+ %Q(<sub>#{escape_html(str)}</sub>)
606
+ end
607
+
608
+ def inline_raw(str)
609
+ %Q(#{str.gsub("\\n", "\n")})
610
+ end
611
+
612
+ def inline_hint(str)
613
+ if @param["nolf"].nil?
614
+ %Q(\n<hint>#{escape_html(str)}</hint>)
615
+ else
616
+ %Q(<hint>#{escape_html(str)}</hint>)
617
+ end
618
+ end
619
+
620
+ def inline_maru(str)
621
+ if str =~ /^\d+$/
622
+ sprintf("&#x%x;", 9311 + str.to_i)
623
+ elsif str =~ /^[A-Za-z]$/
624
+ sprintf("&#x%x;", 9398 + str[0] - 65)
625
+ else
626
+ raise "can't parse maru: #{str}"
627
+ end
628
+ end
629
+
630
+ def inline_idx(str)
631
+ %Q(#{escape_html(str)}<index value="#{escape_html(str)}" />)
632
+ end
633
+
634
+ def inline_hidx(str)
635
+ %Q(<index value="#{escape_html(str)}" />)
636
+ end
637
+
638
+ def inline_ami(str)
639
+ %Q(<ami>#{escape_html(str)}</ami>)
640
+ end
641
+
642
+ def inline_i(str)
643
+ %Q(<i>#{escape_html(str)}</i>)
644
+ end
645
+
646
+ def inline_b(str)
647
+ %Q(<b>#{escape_html(str)}</b>)
648
+ end
649
+
650
+ def inline_tt(str)
651
+ %Q(<tt>#{escape_html(str)}</tt>)
652
+ end
653
+
654
+ def inline_ttbold(str)
655
+ index = escape_html(str).gsub(/<.*?>/, "").gsub(/\*/, "ESCAPED_ASTERISK").gsub(/'/, "&#27;")
656
+ %Q(<tt style='bold'>#{escape_html(str)}</tt><index value='#{index}' />)
657
+ end
658
+
659
+ def inline_tti(str)
660
+ %Q(<tt style='italic'>#{escape_html(str)}</tt>)
661
+ end
662
+
663
+ def inline_u(str)
664
+ %Q(<underline>#{escape_html(str)}</underline>)
665
+ end
666
+
667
+ def inline_icon(id)
668
+ if @param["subdirmode"].nil?
669
+ warn "image file not exist: images/#{@chapter.id}-#{id}.eps" unless File.exist?("images/#{@chapter.id}-#{id}.eps")
670
+ %Q[<Image href="file://images/#{@chapter.id}-#{id}.eps" type='inline'/>]
671
+ else
672
+ warn "image file not exist: images/#{@chapter.id}/#{id}.eps" unless File.exist?("images/#{@chapter.id}/#{id}.eps")
673
+ %Q[<Image href="file://images/#{@chapter.id}/#{id}.eps" type='inline'/>]
674
+ end
675
+ end
676
+
677
+ def inline_bou(str)
678
+ %Q(<bou>#{escape_html(str)}</bou>)
679
+ end
680
+
681
+ def inline_keytop(str)
682
+ %Q(<keytop>#{escape_html(str)}</keytop>)
683
+ end
684
+
685
+ def inline_labelref(idref)
686
+ %Q(<ref idref='#{idref}'>「●● #{idref}」</ref>) # FIXME:節名とタイトルも込みで要出力
687
+ end
688
+
689
+ alias inline_ref inline_labelref
690
+
691
+ def inline_pageref(idref)
692
+ %Q(<pageref idref='#{idref}'>●●</pageref>) # ページ番号を参照
693
+ end
694
+
695
+ def inline_balloon(str)
696
+ %Q(<balloon>#{escape_html(str).gsub(/@maru\[(\d+)\]/) {|m| inline_maru($1)}}</balloon>)
697
+ end
698
+
699
+ def inline_uchar(str)
700
+ %Q(&#x#{str};)
701
+ end
702
+
703
+ def noindent
704
+ @noindent = true
705
+ end
706
+
707
+ def linebreak
708
+ # FIXME:pが閉じちゃってるので一度戻らないといけないが、難しい…。
709
+ puts "<br />"
710
+ end
711
+
712
+ def pagebreak
713
+ puts "<pagebreak />"
714
+ end
715
+
716
+ def nonum_begin(level, label, caption)
717
+ puts %Q(<title aid:pstyle="h#{level}">#{escape_html(caption)}</title><?dtp level="#{level}" section="#{escape_html(caption)}"?>)
718
+ end
719
+
720
+ def nonum_end(level)
721
+ end
722
+
723
+ def circle_begin(level, label, caption)
724
+ puts %Q(<title aid:pstyle="smallcircle">&#x2022;#{escape_html(caption)}</title>)
725
+ end
726
+
727
+ def circle_end(level)
728
+ end
729
+
730
+ def column_begin(level, label, caption)
731
+ print "<column>"
732
+ puts %Q(<title aid:pstyle="column-title">#{escape_html(caption)}</title>)
733
+ end
734
+
735
+ def column_end(level)
736
+ puts "</column>"
737
+ end
738
+
739
+ def xcolumn_begin(level, label, caption)
740
+ print "<xcolumn>"
741
+ puts %Q(<title aid:pstyle="xcolumn-title">#{escape_html(caption)}</title>)
742
+ end
743
+
744
+ def xcolumn_end(level)
745
+ puts "</xcolumn>"
746
+ end
747
+
748
+ def world_begin(level, label, caption)
749
+ print "<worldcolumn>"
750
+ puts %Q(<title aid:pstyle="worldcolumn-title">#{escape_html(caption)}</title>)
751
+ end
752
+
753
+ def world_end(level)
754
+ puts "</worldcolumn>"
755
+ end
756
+
757
+ def hood_begin(level, label, caption)
758
+ print "<hoodcolumn>"
759
+ puts %Q(<title aid:pstyle="hoodcolumn-title">#{escape_html(caption)}</title>)
760
+ end
761
+
762
+ def hood_end(level)
763
+ puts "</hoodcolumn>"
764
+ end
765
+
766
+ def edition_begin(level, label, caption)
767
+ print "<editioncolumn>"
768
+ puts %Q(<title aid:pstyle="editioncolumn-title">#{escape_html(caption)}</title>)
769
+ end
770
+
771
+ def edition_end(level)
772
+ puts "</editioncolumn>"
773
+ end
774
+
775
+ def insideout_begin(level, label, caption)
776
+ print "<insideoutcolumn>"
777
+ puts %Q(<title aid:pstyle="insideoutcolumn-title">#{escape_html(caption)}</title>)
778
+ end
779
+
780
+ def insideout_end(level)
781
+ puts "</insideoutcolumn>"
782
+ end
783
+
784
+ def ref_begin(level, label, caption)
785
+ if !label.nil?
786
+ puts "<reference id='#{label}'>"
787
+ else
788
+ puts "<reference>"
789
+ end
790
+ end
791
+
792
+ def ref_end(level)
793
+ puts "</reference>"
794
+ end
795
+
796
+ def sup_begin(level, label, caption)
797
+ if !label.nil?
798
+ puts "<supplement id='#{label}'>"
799
+ else
800
+ puts "<supplement>"
801
+ end
802
+ end
803
+
804
+ def sup_end(level)
805
+ puts "</supplement>"
806
+ end
807
+
808
+ def flushright(lines)
809
+ puts "<p align='right'>#{lines.join("\n")}</p>"
810
+ end
811
+
812
+ def note(lines, caption = nil)
813
+ print "<note>"
814
+ puts "<title aid:pstyle='note-title'>#{escape_html(caption)}</title>" unless caption.nil?
815
+ puts "#{lines.join("\n")}</note>"
816
+ end
817
+
818
+ def memo(lines, caption = nil)
819
+ print "<memo>"
820
+ puts "<title aid:pstyle='memo-title'>#{escape_html(caption)}</title>" unless caption.nil?
821
+ puts "#{lines.join("\n")}</memo>"
822
+ end
823
+
824
+ def tip(lines, caption = nil)
825
+ print "<tip>"
826
+ puts "<title aid:pstyle='tip-title'>#{escape_html(caption)}</title>" unless caption.nil?
827
+ puts "#{lines.join("\n")}</tip>"
828
+ end
829
+
830
+ def info(lines, caption = nil)
831
+ print "<info>"
832
+ puts "<title aid:pstyle='info-title'>#{escape_html(caption)}</title>" unless caption.nil?
833
+ puts "#{lines.join("\n")}</info>"
834
+ end
835
+
836
+ def planning(lines, caption = nil)
837
+ print "<planning>"
838
+ puts "<title aid:pstyle='planning-title'>#{escape_html(caption)}</title>" unless caption.nil?
839
+ puts "#{lines.join("\n")}</planning>"
840
+ end
841
+
842
+ def best(lines, caption = nil)
843
+ print "<best>"
844
+ puts "<title aid:pstyle='best-title'>#{escape_html(caption)}</title>" unless caption.nil?
845
+ puts "#{lines.join("\n")}</best>"
846
+ end
847
+
848
+ def important(lines, caption = nil)
849
+ print "<important>"
850
+ puts "<title aid:pstyle='important-title'>#{escape_html(caption)}</title>" unless caption.nil?
851
+ puts "#{lines.join("\n")}</important>"
852
+ end
853
+
854
+ def security(lines, caption = nil)
855
+ print "<security>"
856
+ puts "<title aid:pstyle='security-title'>#{escape_html(caption)}</title>" unless caption.nil?
857
+ puts "#{lines.join("\n")}</security>"
858
+ end
859
+
860
+ def caution(lines, caption = nil)
861
+ print "<caution>"
862
+ puts "<title aid:pstyle='caution-title'>#{escape_html(caption)}</title>" unless caption.nil?
863
+ puts "#{lines.join("\n")}</caution>"
864
+ end
865
+
866
+ def term(lines)
867
+ puts "<term>#{lines.join("\n")}</term>"
868
+ end
869
+
870
+ def link(lines, caption = nil)
871
+ print "<link>"
872
+ puts "<title aid:pstyle='link-title'>#{escape_html(caption)}</title>" unless caption.nil?
873
+ puts "#{lines.join("\n")}</link>"
874
+ end
875
+
876
+ def notice(lines, caption = nil)
877
+ if caption.nil?
878
+ puts "<notice>#{lines.join("\n")}</notice>"
879
+ else
880
+ puts "<notice-t><title aid:pstyle='notice-title'>#{escape_html(caption)}</title>"
881
+ puts "#{lines.join("\n")}</notice-t>"
882
+ end
883
+ end
884
+
885
+ def point(lines, caption = nil)
886
+ if caption.nil?
887
+ puts "<point>#{lines.join("\n")}</point>"
888
+ else
889
+ puts "<point-t><title aid:pstyle='point-title'>#{escape_html(caption)}</title>"
890
+ puts "#{lines.join("\n")}</point-t>"
891
+ end
892
+ end
893
+
894
+ def shoot(lines, caption = nil)
895
+ if caption.nil?
896
+ puts "<shoot>#{lines.join("\n")}</shoot>"
897
+ else
898
+ puts "<shoot-t><title aid:pstyle='shoot-title'>#{escape_html(caption)}</title>"
899
+ puts "#{lines.join("\n")}</shoot-t>"
900
+ end
901
+ end
902
+
903
+ def reference(lines)
904
+ puts "<reference>#{lines.join("\n")}</reference>"
905
+ end
906
+
907
+ def practice(lines)
908
+ puts "<practice>#{lines.join("\n")}</practice>"
909
+ end
910
+
911
+ def expert(lines)
912
+ puts "<expert>#{lines.join("\n")}</expert>"
913
+ end
914
+
915
+ def insn(lines, caption = nil)
916
+ if caption.nil?
917
+ puts %Q[<insn>]
918
+ else
919
+ puts %Q[<insn><floattitle type="insn">#{escape_html(caption)}</floattitle>]
920
+ end
921
+ no = 1
922
+ lines.each do |line|
923
+ unless @param["listinfo"].nil?
924
+ print "<listinfo line=\"#{no}\""
925
+ print " begin=\"1\"" if no == 1
926
+ print " end=\"#{no}\"" if no == lines.size
927
+ print ">"
928
+ end
929
+ print detab(line)
930
+ print "\n"
931
+ print "</listinfo>" unless @param["listinfo"].nil?
932
+ no += 1
933
+ end
934
+ puts "</insn>"
935
+ end
936
+
937
+ def box(lines, caption = nil)
938
+ if caption.nil?
939
+ print %Q[<box>]
940
+ else
941
+ puts %Q[<box><caption aid:pstyle="box-title">#{escape_html(caption)}</caption>]
942
+ end
943
+ no = 1
944
+ lines.each do |line|
945
+ unless @param["listinfo"].nil?
946
+ print "<listinfo line=\"#{no}\""
947
+ print " begin=\"1\"" if no == 1
948
+ print " end=\"#{no}\"" if no == lines.size
949
+ print ">"
950
+ end
951
+ print detab(line)
952
+ print "\n"
953
+ print "</listinfo>" unless @param["listinfo"].nil?
954
+ no += 1
955
+ end
956
+ puts "</box>"
957
+ end
958
+
959
+ def indepimage(id)
960
+ puts "<img>"
961
+ if @param["subdirmode"].nil?
962
+ warn "image file not exist: images/#{@chapter.id}-#{id}.eps" unless File.exist?("images/#{@chapter.id}-#{id}.eps")
963
+ puts %Q[<Image href="file://images/#{@chapter.id}-#{id}.eps" />]
964
+ else
965
+ warn "image file not exist: images/#{@chapter.id}/#{id}.eps" unless File.exist?("images/#{@chapter.id}/#{id}.eps")
966
+ puts %Q[<Image href="file://images/#{@chapter.id}/#{id}.eps" />]
967
+ end
968
+ puts "</img>"
969
+ end
970
+
971
+ def label(id)
972
+ # FIXME
973
+ print "<label id='#{id}' />"
974
+ end
975
+
976
+ def tsize(str)
977
+ @tsize = str
978
+ end
979
+
980
+ def dtp(str)
981
+ print %Q(<?dtp #{str} ?>)
982
+ end
983
+
984
+ def hr
985
+ print "<hr/>"
986
+ end
987
+
988
+ def bpo(lines)
989
+ puts %Q[<bpo>#{lines.join("\n")}</bpo>]
990
+ end
991
+
992
+ def inline_dtp(str)
993
+ "<?dtp #{str} ?>"
994
+ end
995
+
996
+ def inline_code(str)
997
+ %Q(<tt type='inline-code'>#{escape_html(str)}</tt>)
998
+ end
999
+
1000
+ def rawblock(lines)
1001
+ no = 1
1002
+ lines.each {|l|
1003
+ print l.gsub("&lt;", "<").gsub("&gt;", ">").gsub("&quot;", "\"").gsub("&amp;", "&")
1004
+ print "\n" unless lines.length == no
1005
+ no = no + 1
1006
+ }
1007
+ end
1008
+
1009
+ def text(str)
1010
+ str
1011
+ end
1012
+
1013
+ def inline_chapref(id)
1014
+ chs = ["", "「", "」"]
1015
+ unless @param["chapref"].nil?
1016
+ _chs = NKF.nkf("-w", @param["chapref"]).split(",")
1017
+ if _chs.size != 3
1018
+ error "--chapsplitter must have exactly 3 parameters with comma."
1019
+ else
1020
+ chs = _chs
1021
+ end
1022
+ else
1023
+ end
1024
+ "#{chs[0]}#{@chapter.env.chapter_index.number(id)}#{chs[1]}#{@chapter.env.chapter_index.title(id)}#{chs[2]}"
1025
+ rescue KeyError
1026
+ error "unknown chapter: #{id}"
1027
+ nofunc_text("[UnknownChapter:#{id}]")
1028
+ end
1029
+
1030
+ def source_header(caption)
1031
+ puts %Q[<source>]
1032
+ puts %Q[<caption>#{escape_html(caption)}</caption>]
1033
+ end
1034
+
1035
+ def source_body(lines)
1036
+ puts %Q[<pre>]
1037
+ lines.each do |line|
1038
+ print detab(line)
1039
+ print "\n"
1040
+ end
1041
+ puts %Q[</pre></source>]
1042
+ end
1043
+
1044
+ def bibpaper(lines, id, caption)
1045
+ bibpaper_header id, caption
1046
+ unless lines.empty?
1047
+ bibpaper_bibpaper id, caption, lines
1048
+ end
1049
+ puts %Q(</bibitem>)
1050
+ end
1051
+
1052
+ def bibpaper_header(id, caption)
1053
+ puts %Q(<bibitem id="bib-#{id}">)
1054
+ puts "<caption><span type='bibno'>[#{@chapter.bibpaper(id).number}] </span>#{escape_html(caption)}</caption>"
1055
+ end
1056
+
1057
+ def bibpaper_bibpaper(id, caption, lines)
1058
+ lines.each do |line|
1059
+ puts detab(line)
1060
+ end
1061
+ end
1062
+
1063
+ def inline_bib(id)
1064
+ %Q(<span type='bibref' idref='#{id}'>[#{@chapter.bibpaper(id).number}]</span>)
1065
+ end
1066
+
1067
+ def inline_recipe(id)
1068
+ # FIXME
1069
+ %Q(<recipe idref="#{escape_html(id)}">[XXX]「#{escape_html(id)}」\tp.XX</recipe>)
1070
+ end
1071
+
1072
+ def nofunc_text(str)
1073
+ escape_html(str)
1074
+ end
1075
+
1076
+ end
1077
+
1078
+ end # module ReVIEW