review 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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