review 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/.travis.yml +1 -2
  2. data/ChangeLog +65 -0
  3. data/Gemfile +5 -0
  4. data/README.rdoc +6 -1
  5. data/Rakefile +14 -28
  6. data/bin/review-check +9 -21
  7. data/bin/review-compile +45 -12
  8. data/bin/review-epubmaker +477 -220
  9. data/bin/review-epubmaker-ng +5 -14
  10. data/bin/review-index +4 -2
  11. data/bin/review-init +94 -0
  12. data/bin/review-pdfmaker +70 -287
  13. data/bin/review-preproc +5 -2
  14. data/bin/review-vol +4 -11
  15. data/debian/changelog +3 -3
  16. data/debian/copyright +5 -3
  17. data/debian/docs +1 -0
  18. data/doc/format.rdoc +57 -11
  19. data/doc/quickstart.rdoc +4 -4
  20. data/doc/sample.yaml +11 -7
  21. data/lib/epubmaker.rb +1 -1
  22. data/lib/epubmaker/epubv2.rb +26 -27
  23. data/lib/epubmaker/epubv3.rb +13 -13
  24. data/lib/epubmaker/producer.rb +1 -1
  25. data/lib/review.rb +3 -4
  26. data/lib/review/book.rb +17 -581
  27. data/lib/review/book/base.rb +247 -0
  28. data/lib/review/book/chapter.rb +81 -0
  29. data/lib/review/book/compilable.rb +163 -0
  30. data/lib/review/book/index.rb +339 -0
  31. data/lib/review/book/page_metric.rb +38 -0
  32. data/lib/review/book/parameters.rb +97 -0
  33. data/lib/review/book/part.rb +44 -0
  34. data/lib/review/book/volume.rb +65 -0
  35. data/lib/review/builder.rb +34 -40
  36. data/lib/review/compiler.rb +32 -13
  37. data/lib/review/configure.rb +38 -0
  38. data/lib/review/ewbbuilder.rb +23 -21
  39. data/lib/review/extentions.rb +3 -0
  40. data/lib/review/extentions/object.rb +9 -0
  41. data/lib/review/{compat.rb → extentions/string.rb} +11 -0
  42. data/lib/review/htmlbuilder.rb +162 -74
  43. data/lib/review/htmlutils.rb +28 -1
  44. data/lib/review/i18n.yaml +11 -0
  45. data/lib/review/idgxmlbuilder.rb +119 -35
  46. data/lib/review/inaobuilder.rb +355 -0
  47. data/lib/review/latexbuilder.rb +133 -59
  48. data/lib/review/latexutils.rb +15 -6
  49. data/lib/review/makerhelper.rb +59 -0
  50. data/lib/review/markdownbuilder.rb +129 -0
  51. data/lib/review/preprocessor.rb +20 -7
  52. data/lib/review/review.tex.erb +250 -0
  53. data/lib/review/textutils.rb +28 -3
  54. data/lib/review/tocparser.rb +20 -12
  55. data/lib/review/tocprinter.rb +7 -3
  56. data/lib/review/topbuilder.rb +44 -27
  57. data/lib/review/version.rb +3 -0
  58. data/review.gemspec +20 -117
  59. data/test/book_test_helper.rb +35 -0
  60. data/test/sample-book/README.md +5 -0
  61. data/test/sample-book/src/CHAPS +2 -0
  62. data/test/sample-book/src/PREDEF +1 -0
  63. data/test/sample-book/src/Rakefile +26 -0
  64. data/test/sample-book/src/_cover.html +3 -0
  65. data/test/sample-book/src/ch01.re +71 -0
  66. data/test/sample-book/src/ch02.re +3 -0
  67. data/test/sample-book/src/config.yml +55 -0
  68. data/test/sample-book/src/images/ch01-imgsample.jpg +0 -0
  69. data/test/sample-book/src/images/cover.jpg +0 -0
  70. data/test/sample-book/src/main.css +251 -0
  71. data/test/sample-book/src/preface.re +15 -0
  72. data/test/sample-book/src/sty/jumoline.sty +310 -0
  73. data/test/sample-book/src/sty/samplemacro.sty +21 -0
  74. data/test/sample-book/src/vendor/jumoline/README +29 -0
  75. data/test/sample-book/src/vendor/jumoline/jumoline.dtx +2988 -0
  76. data/test/sample-book/src/vendor/jumoline/jumoline.ins +6 -0
  77. data/test/test_book.rb +26 -646
  78. data/test/test_book_chapter.rb +418 -0
  79. data/test/test_book_parameter.rb +42 -0
  80. data/test/test_book_part.rb +53 -0
  81. data/test/test_builder.rb +17 -10
  82. data/test/test_compiler.rb +46 -0
  83. data/test/test_epubmaker.rb +1 -1
  84. data/test/test_epubmaker_cmd.rb +36 -0
  85. data/test/test_helper.rb +17 -0
  86. data/test/test_htmlbuilder.rb +156 -24
  87. data/test/test_htmlutils.rb +4 -0
  88. data/test/test_i18n.rb +6 -2
  89. data/test/test_idgxmlbuilder.rb +33 -11
  90. data/test/test_inaobuilder.rb +247 -0
  91. data/test/test_index.rb +31 -0
  92. data/test/test_latexbuilder.rb +115 -35
  93. data/test/test_makerhelper.rb +50 -0
  94. data/test/test_pdfmaker_cmd.rb +36 -0
  95. data/test/test_preprocessor.rb +7 -7
  96. data/test/test_topbuilder.rb +6 -7
  97. data/test/test_uuid.rb +1 -0
  98. metadata +117 -12
  99. data/lib/review/index.rb +0 -323
  100. data/lib/review/volume.rb +0 -66
@@ -27,6 +27,33 @@ module ReVIEW
27
27
  # FIXME better code
28
28
  str.gsub('&quot;', '"').gsub('&gt;', '>').gsub('&lt;', '<').gsub('&amp;', '&')
29
29
  end
30
- end
31
30
 
31
+ def strip_html(str)
32
+ str.gsub(/<\/?[^>]*>/, "")
33
+ end
34
+
35
+ def highlight(ops)
36
+ body = ops[:body] || ''
37
+ lexer = ops[:lexer] || ''
38
+ format = ops[:format] || ''
39
+
40
+ begin
41
+ require 'pygments'
42
+ begin
43
+ Pygments.highlight(
44
+ unescape_html(body),
45
+ :options => {
46
+ :nowrap => true,
47
+ :noclasses => true
48
+ },
49
+ :formatter => format,
50
+ :lexer => lexer)
51
+ rescue MentosError
52
+ body
53
+ end
54
+ rescue LoadError
55
+ body
56
+ end
57
+ end
58
+ end
32
59
  end # module ReVIEW
@@ -2,13 +2,19 @@ ja:
2
2
  image: 図
3
3
  table: 表
4
4
  list: リスト
5
+ part: 第%d部
5
6
  chapter: 第%d章
6
7
  chapter_postfix: " "
8
+ appendix: 付録%d
7
9
  numberless_image: "図:"
8
10
  format_number: "%s.%d"
9
11
  format_number_header: "%s.%d:"
10
12
  format_number_without_chapter: "%d"
11
13
  format_number_header_without_chapter: "%d:"
14
+ caption_prefix: " "
15
+ caption_prefix_idgxml: " "
16
+ ruby_prefix: "("
17
+ ruby_postfix: ")"
12
18
 
13
19
  en:
14
20
  image: "Figure "
@@ -16,8 +22,13 @@ en:
16
22
  list: "List "
17
23
  chapter: Chapter %d
18
24
  chapter_postfix: ". "
25
+ appendix: Appendix %s
19
26
  numberless_image: "Figure:"
20
27
  format_number: "%s.%d"
21
28
  format_number_header: "%s.%d:"
22
29
  format_number_without_chapter: "%d"
23
30
  format_number_header_without_chapter: "%d:"
31
+ caption_prefix: " "
32
+ caption_prefix_idgxml: " "
33
+ ruby_prefix: "("
34
+ ruby_postfix: ")"
@@ -76,6 +76,7 @@ module ReVIEW
76
76
  print %Q(<?xml version="1.0" encoding="UTF-8"?>\n)
77
77
  print %Q(<#{@rootelement} xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/">)
78
78
  alias puts print unless ReVIEW.book.param["nolf"].nil?
79
+ @secttags = true unless ReVIEW.book.param["structuredxml"].nil?
79
80
  end
80
81
  private :builder_init_file
81
82
 
@@ -145,10 +146,19 @@ module ReVIEW
145
146
  end
146
147
 
147
148
  print %Q(<chapter id="chap:#{@chapter.number}">) unless @secttags.nil?
148
- if @chapter.number.to_s =~ /\A\d+$/
149
- prefix = "#{I18n.t("chapter", @chapter.number)}#{I18n.t("chapter_postfix")}"
150
- elsif !@chapter.number.nil? && !@chapter.number.to_s.empty?
151
- prefix = "#{@chapter.number}#{I18n.t("chapter_postfix")}"
149
+
150
+ if @chapter.number.blank?
151
+ prefix = ""
152
+ else
153
+ placeholder = if @chapter.is_a? ReVIEW::Book::Part
154
+ level = 0
155
+ 'part'
156
+ elsif @chapter.on_POSTDEF?
157
+ 'appendix'
158
+ else
159
+ 'chapter'
160
+ end
161
+ prefix = "#{I18n.t(placeholder, @chapter.number)}#{I18n.t("chapter_postfix")}"
152
162
  end
153
163
  @section = 0
154
164
  @subsection = 0
@@ -163,8 +173,13 @@ module ReVIEW
163
173
  end
164
174
  @section += 1
165
175
  print %Q(<sect id="sect:#{@chapter.number}.#{@section}">) unless @secttags.nil?
166
-
167
- prefix = (!@chapter.number.nil? && !@chapter.number.to_s.empty?) ? "#{@chapter.number}.#{@section} " : ""
176
+ if ReVIEW.book.param["secnolevel"] >= 2
177
+ if @chapter.number.blank? or @chapter.on_POSTDEF?
178
+ prefix = ""
179
+ else
180
+ prefix = "#{@chapter.number}.#{@section}#{I18n.t("chapter_postfix")}"
181
+ end
182
+ end
168
183
 
169
184
  @subsection = 0
170
185
  @subsubsection = 0
@@ -178,7 +193,13 @@ module ReVIEW
178
193
 
179
194
  @subsection += 1
180
195
  print %Q(<sect2 id="sect:#{@chapter.number}.#{@section}.#{@subsection}">) unless @secttags.nil?
181
- prefix = (!@chapter.number.nil? && !@chapter.number.to_s.empty?) ? "#{@chapter.number}.#{@section}.#{@subsection} " : ""
196
+ if ReVIEW.book.param["secnolevel"] >= 3
197
+ if @chapter.number.blank? or @chapter.on_POSTDEF?
198
+ prefix = ""
199
+ else
200
+ prefix = "#{@chapter.number}.#{@section}.#{@subsection}#{I18n.t("chapter_postfix")}"
201
+ end
202
+ end
182
203
 
183
204
  @subsubsection = 0
184
205
  @subsubsubsection = 0
@@ -189,8 +210,14 @@ module ReVIEW
189
210
  end
190
211
 
191
212
  @subsubsection += 1
192
- print %Q(<sect3 id="sect:#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection}">) unless @secttags.nil?
193
- prefix = (!@chapter.number.nil? && !@chapter.number.to_s.empty?) ? "#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection} " : ""
213
+ print %Q(<sect3 id="sect:#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection}">) unless @secttags.nil?
214
+ if ReVIEW.book.param["secnolevel"] >= 4
215
+ if @chapter.number.blank? or @chapter.on_POSTDEF?
216
+ prefix = ""
217
+ else
218
+ prefix = "#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection}#{I18n.t("chapter_postfix")}"
219
+ end
220
+ end
194
221
 
195
222
  @subsubsubsection = 0
196
223
  when 5
@@ -200,17 +227,24 @@ module ReVIEW
200
227
 
201
228
  @subsubsubsection += 1
202
229
  print %Q(<sect4 id="sect:#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection}.#{@subsubsubsection}">) unless @secttags.nil?
203
- prefix = (!@chapter.number.nil? && !@chapter.number.to_s.empty?) ? "#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection}.#{@subsubsubsection} " : ""
230
+ if ReVIEW.book.param["secnolevel"] >= 5
231
+ if @chapter.number.blank? or @chapter.on_POSTDEF?
232
+ prefix = ""
233
+ else
234
+ prefix = "#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection}.#{@subsubsubsection}#{I18n.t("chapter_postfix")}"
235
+ end
236
+ end
237
+
204
238
  else
205
239
  raise "caption level too deep or unsupported: #{level}"
206
240
  end
207
241
 
208
242
  prefix = "" if (level.to_i > ReVIEW.book.param["secnolevel"])
209
243
  label = label.nil? ? "" : " id=\"#{label}\""
210
- puts %Q(<title#{label} aid:pstyle="h#{level}">#{prefix}#{compile_inline(caption)}</title><?dtp level="#{level}" section="#{prefix}#{escape_html(compile_inline(caption))}"?>)
244
+ toccaption = escape_html(compile_inline(caption.gsub(/@<fn>\{.+?\}/, '')).gsub(/<[^>]+>/, ''))
245
+ puts %Q(<title#{label} aid:pstyle="h#{level}">#{prefix}#{compile_inline(caption)}</title><?dtp level="#{level}" section="#{prefix}#{toccaption}"?>)
211
246
  end
212
247
 
213
-
214
248
  def ul_begin
215
249
  level = block_given? ? yield : ""
216
250
  level = nil if level == 1
@@ -314,14 +348,13 @@ module ReVIEW
314
348
  def list_header(id, caption)
315
349
  puts %Q[<codelist>]
316
350
  if get_chap.nil?
317
- puts %Q[<caption>#{I18n.t("list")}#{I18n.t("format_number_without_chapter", [@chapter.list(id).number])} #{compile_inline(caption)}</caption>]
351
+ puts %Q[<caption>#{I18n.t("list")}#{I18n.t("format_number_without_chapter", [@chapter.list(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}</caption>]
318
352
  else
319
- puts %Q[<caption>#{I18n.t("list")}#{I18n.t("format_number", [get_chap, @chapter.list(id).number])} #{compile_inline(caption)}</caption>]
353
+ puts %Q[<caption>#{I18n.t("list")}#{I18n.t("format_number", [get_chap, @chapter.list(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}</caption>]
320
354
  end
321
355
  end
322
356
 
323
- def list_body(lines)
324
- print %Q(<pre>)
357
+ def codelines_body(lines)
325
358
  no = 1
326
359
  lines.each do |line|
327
360
  unless ReVIEW.book.param["listinfo"].nil?
@@ -335,6 +368,11 @@ module ReVIEW
335
368
  print "</listinfo>" unless ReVIEW.book.param["listinfo"].nil?
336
369
  no += 1
337
370
  end
371
+ end
372
+
373
+ def list_body(id, lines)
374
+ print %Q(<pre>)
375
+ codelines_body(lines)
338
376
  puts "</pre></codelist>"
339
377
  end
340
378
 
@@ -347,14 +385,23 @@ module ReVIEW
347
385
  lines.each_with_index do |line, i|
348
386
  _lines << detab("<span type='lineno'>" + (i + 1).to_s.rjust(2) + ": </span>" + line)
349
387
  end
350
- quotedlist _lines, 'emlist', caption
388
+ quotedlist _lines, 'emlistnum', caption
351
389
  end
352
390
 
353
391
  def listnum_body(lines)
354
392
  print %Q(<pre>)
393
+ no = 1
355
394
  lines.each_with_index do |line, i|
395
+ unless ReVIEW.book.param["listinfo"].nil?
396
+ print "<listinfo line=\"#{no}\""
397
+ print " begin=\"1\"" if no == 1
398
+ print " end=\"#{no}\"" if no == lines.size
399
+ print ">"
400
+ end
356
401
  print detab("<span type='lineno'>" + (i + 1).to_s.rjust(2) + ": </span>" + line)
357
402
  print "\n"
403
+ print "</listinfo>" unless ReVIEW.book.param["listinfo"].nil?
404
+ no += 1
358
405
  end
359
406
  puts "</pre></codelist>"
360
407
  end
@@ -449,9 +496,9 @@ module ReVIEW
449
496
 
450
497
  def image_header(id, caption)
451
498
  if get_chap.nil?
452
- puts %Q[<caption>#{I18n.t("image")}#{I18n.t("format_number_without_chapter", [@chapter.image(id).number])} #{compile_inline(caption)}</caption>]
499
+ puts %Q[<caption>#{I18n.t("image")}#{I18n.t("format_number_without_chapter", [@chapter.image(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}</caption>]
453
500
  else
454
- puts %Q[<caption>#{I18n.t("image")}#{I18n.t("format_number", [get_chap, @chapter.image(id).number])} #{compile_inline(caption)}</caption>]
501
+ puts %Q[<caption>#{I18n.t("image")}#{I18n.t("format_number", [get_chap, @chapter.image(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}</caption>]
455
502
  end
456
503
  end
457
504
 
@@ -559,9 +606,9 @@ module ReVIEW
559
606
 
560
607
  def table_header(id, caption)
561
608
  if get_chap.nil?
562
- puts %Q[<caption>#{I18n.t("table")}#{I18n.t("format_number_without_chapter", [@chapter.table(id).number])} #{compile_inline(caption)}</caption>]
609
+ puts %Q[<caption>#{I18n.t("table")}#{I18n.t("format_number_without_chapter", [@chapter.table(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}</caption>]
563
610
  else
564
- puts %Q[<caption>#{I18n.t("table")}#{I18n.t("format_number", [get_chap, @chapter.table(id).number])} #{compile_inline(caption)}</caption>]
611
+ puts %Q[<caption>#{I18n.t("table")}#{I18n.t("format_number", [get_chap, @chapter.table(id).number])}#{I18n.t("caption_prefix_idgxml")}#{compile_inline(caption)}</caption>]
565
612
  end
566
613
  end
567
614
 
@@ -616,7 +663,7 @@ module ReVIEW
616
663
  end
617
664
 
618
665
  def compile_href(url, label)
619
- %Q[<a linkurl='#{url}'>#{label.nil? ? url : label}</a>]
666
+ %Q[<a linkurl='#{escape_html(url)}'>#{label.nil? ? escape_html(url) : escape_html(label)}</a>]
620
667
  end
621
668
 
622
669
  def inline_sup(str)
@@ -716,13 +763,13 @@ module ReVIEW
716
763
  end
717
764
 
718
765
  def inline_labelref(idref)
719
- %Q[<ref idref='#{idref}'>「●● #{idref}」</ref>] # FIXME:節名とタイトルも込みで要出力
766
+ %Q[<ref idref='#{escape_html(idref)}'>「●● #{escape_html(idref)}」</ref>] # FIXME:節名とタイトルも込みで要出力
720
767
  end
721
768
 
722
769
  alias inline_ref inline_labelref
723
770
 
724
771
  def inline_pageref(idref)
725
- %Q[<pageref idref='#{idref}'>●●</pageref>] # ページ番号を参照
772
+ %Q[<pageref idref='#{escape_html(idref)}'>●●</pageref>] # ページ番号を参照
726
773
  end
727
774
 
728
775
  def inline_balloon(str)
@@ -854,6 +901,10 @@ module ReVIEW
854
901
  end
855
902
  end
856
903
 
904
+ def centering(lines)
905
+ puts split_paragraph(lines).join.gsub("<p>", "<p align='center'>")
906
+ end
907
+
857
908
  def captionblock(type, lines, caption, specialstyle = nil)
858
909
  print "<#{type}>"
859
910
  style = specialstyle.nil? ? "#{type}-title" : specialstyle
@@ -982,8 +1033,8 @@ module ReVIEW
982
1033
  syntaxblock("box", lines, caption)
983
1034
  end
984
1035
 
985
- def indepimage(id, caption=nil, metric=nil)
986
- metrics = parse_metric("idgxml", metric)
1036
+ def indepimage(id, caption=nil, metric=nil)
1037
+ metrics = parse_metric("idgxml", metric)
987
1038
  puts "<img>"
988
1039
  begin
989
1040
  puts %Q[<Image href="file://#{@chapter.image(id).path.sub(/\A\.\//, "")}"#{metrics} />]
@@ -1045,7 +1096,8 @@ module ReVIEW
1045
1096
  def inline_chapref(id)
1046
1097
  chs = ["", "「", "」"]
1047
1098
  unless ReVIEW.book.param["chapref"].nil?
1048
- _chs = NKF.nkf("-w", ReVIEW.book.param["chapref"]).split(",")
1099
+ _chs = convert_inencoding(ReVIEW.book.param["chapref"],
1100
+ ReVIEW.book.param["inencoding"]).split(",")
1049
1101
  if _chs.size != 3
1050
1102
  error "--chapsplitter must have exactly 3 parameters with comma."
1051
1103
  else
@@ -1053,7 +1105,34 @@ module ReVIEW
1053
1105
  end
1054
1106
  else
1055
1107
  end
1056
- "#{chs[0]}#{@chapter.env.chapter_index.number(id)}#{chs[1]}#{@chapter.env.chapter_index.title(id)}#{chs[2]}"
1108
+ s = "#{chs[0]}#{@chapter.env.chapter_index.number(id)}#{chs[1]}#{@chapter.env.chapter_index.title(id)}#{chs[2]}"
1109
+ if ReVIEW.book.param["chapterlink"]
1110
+ %Q(<link href="#{id}">#{s}</link>)
1111
+ else
1112
+ s
1113
+ end
1114
+ rescue KeyError
1115
+ error "unknown chapter: #{id}"
1116
+ nofunc_text("[UnknownChapter:#{id}]")
1117
+ end
1118
+
1119
+ def inline_chap(id)
1120
+ if ReVIEW.book.param["chapterlink"]
1121
+ %Q(<link href="#{id}">#{@chapter.env.chapter_index.number(id)}</link>)
1122
+ else
1123
+ @chapter.env.chapter_index.number(id)
1124
+ end
1125
+ rescue KeyError
1126
+ error "unknown chapter: #{id}"
1127
+ nofunc_text("[UnknownChapter:#{id}]")
1128
+ end
1129
+
1130
+ def inline_title(id)
1131
+ if ReVIEW.book.param["chapterlink"]
1132
+ %Q(<link href="#{id}">#{@chapter.env.chapter_index.title(id)}</link>)
1133
+ else
1134
+ @chapter.env.chapter_index.title(id)
1135
+ end
1057
1136
  rescue KeyError
1058
1137
  error "unknown chapter: #{id}"
1059
1138
  nofunc_text("[UnknownChapter:#{id}]")
@@ -1066,10 +1145,7 @@ module ReVIEW
1066
1145
 
1067
1146
  def source_body(lines)
1068
1147
  puts %Q[<pre>]
1069
- lines.each do |line|
1070
- print detab(line)
1071
- print "\n"
1072
- end
1148
+ codelines_body(lines)
1073
1149
  puts %Q[</pre></source>]
1074
1150
  end
1075
1151
 
@@ -1087,15 +1163,23 @@ module ReVIEW
1087
1163
  end
1088
1164
 
1089
1165
  def bibpaper_bibpaper(id, caption, lines)
1090
- lines.each do |line|
1091
- puts detab(line)
1092
- end
1166
+ print split_paragraph(lines).join("")
1093
1167
  end
1094
1168
 
1095
1169
  def inline_bib(id)
1096
1170
  %Q(<span type='bibref' idref='#{id}'>[#{@chapter.bibpaper(id).number}]</span>)
1097
1171
  end
1098
1172
 
1173
+ def inline_hd_chap(chap, id)
1174
+ if chap.number
1175
+ n = chap.headline_index.number(id)
1176
+ if ReVIEW.book.param["secnolevel"] >= n.split('.').size
1177
+ return "「#{n} #{compile_inline(chap.headline(id).caption)}」"
1178
+ end
1179
+ end
1180
+ "「#{compile_inline(chap.headline(id).caption)}」"
1181
+ end
1182
+
1099
1183
  def inline_recipe(id)
1100
1184
  # FIXME
1101
1185
  %Q(<recipe idref="#{escape_html(id)}">[XXX]「#{escape_html(id)}」 p.XX</recipe>)
@@ -0,0 +1,355 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (c) 2012 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
+ # INAO Style (experimental)
10
+
11
+ require 'review/builder'
12
+ require 'review/textutils'
13
+
14
+ module ReVIEW
15
+
16
+ class INAOBuilder < Builder
17
+
18
+ include TextUtils
19
+
20
+ def pre_paragraph
21
+ ''
22
+ end
23
+
24
+ def post_paragraph
25
+ ''
26
+ end
27
+
28
+ def extname
29
+ '.txt'
30
+ end
31
+
32
+ def builder_init_file
33
+ @blank_seen = true
34
+ @noindent = nil
35
+
36
+ @titles = {
37
+ "emlist" => "list",
38
+ "list" => "list",
39
+ "cmd" => "list",
40
+ "source" => "list",
41
+ "quote" => "quote",
42
+ "column" => "column",
43
+ }
44
+ end
45
+ private :builder_init_file
46
+
47
+ def print(s)
48
+ @blank_seen = false
49
+ super
50
+ end
51
+ private :print
52
+
53
+ def puts(s)
54
+ @blank_seen = false
55
+ super
56
+ end
57
+ private :puts
58
+
59
+ def blank
60
+ @output.puts unless @blank_seen
61
+ @blank_seen = true
62
+ end
63
+ private :blank
64
+
65
+ def result
66
+ @output.string
67
+ end
68
+
69
+ def warn(msg)
70
+ $stderr.puts "#{@location.filename}:#{@location.lineno}: warning: #{msg}"
71
+ end
72
+
73
+ def error(msg)
74
+ $stderr.puts "#{@location.filename}:#{@location.lineno}: error: #{msg}"
75
+ end
76
+
77
+ def messages
78
+ error_messages() + warning_messages()
79
+ end
80
+
81
+ def base_parablock(type, lines, caption=nil)
82
+ puts "◆#{@titles[type]}/◆"
83
+ puts "■■■■■#{compile_inline(caption)}" unless caption.nil?
84
+ puts split_paragraph(lines).join("\n")
85
+ puts "◆/#{@titles[type]}◆"
86
+ blank
87
+ end
88
+
89
+ def headline(level, label, caption)
90
+ prefix = "■" * level
91
+ puts "#{prefix}#{compile_inline(caption)}"
92
+ end
93
+
94
+ def paragraph(lines)
95
+ print " " if @noindent.nil?
96
+ @noindent = nil
97
+ puts lines.join
98
+ end
99
+
100
+ def noindent
101
+ @noindent = true
102
+ end
103
+
104
+ def inline_b(str)
105
+ "◆b/◆#{str}◆/b◆"
106
+ end
107
+
108
+ def inline_i(str)
109
+ "◆i/◆#{str}◆/i◆"
110
+ end
111
+
112
+ def inline_tt(str)
113
+ "◆cmd/◆#{str}◆/cmd◆"
114
+ end
115
+
116
+ def inline_cmd(str)
117
+ inline_tt(str)
118
+ end
119
+
120
+ def footnote(id, str)
121
+ #
122
+ end
123
+
124
+ def inline_fn(id)
125
+ "◆注/◆#{compile_inline(@chapter.footnote(id).content.strip)}◆/注◆"
126
+ end
127
+
128
+ def inline_keytop(str)
129
+ "#{str}▲"
130
+ end
131
+
132
+ def inline_kbd(str)
133
+ inline_keytop(str)
134
+ end
135
+
136
+ # 「赤文字」はなし
137
+
138
+ def compile_ruby(base, ruby)
139
+ "◆ルビ/◆#{base}◆#{ruby}◆/ルビ◆"
140
+ end
141
+
142
+ def quote(lines)
143
+ base_parablock "quote", lines, nil
144
+ end
145
+
146
+ def column_begin(level, label, caption)
147
+ puts "◆column/◆"
148
+ puts "■■■■#{compile_inline(caption)}"
149
+
150
+ end
151
+
152
+ def column_end(level)
153
+ puts "◆/column◆"
154
+ end
155
+
156
+ def ul_begin
157
+ end
158
+
159
+ def ul_item(lines)
160
+ puts "・#{lines.join}"
161
+ end
162
+
163
+ def ul_end
164
+ end
165
+
166
+ def ol_begin
167
+ @olitem = 0
168
+ end
169
+
170
+ def ol_item(lines, num)
171
+ puts "(#{num})#{lines.join}"
172
+ end
173
+
174
+ def ol_end
175
+ @olitem = nil
176
+ end
177
+
178
+ def inline_list(id)
179
+ chapter, id = extract_chapter_id(id)
180
+ if get_chap(chapter).nil?
181
+ %Q[リスト#{@chapter.list(id).number}]
182
+ else
183
+ %Q[リスト#{get_chap(chapter)}.#{@chapter.list(id).number}]
184
+ end
185
+ end
186
+
187
+ def list_header(id, caption)
188
+ puts "◆list/◆"
189
+ if get_chap.nil?
190
+ puts %Q[●リスト#{@chapter.list(id).number} #{compile_inline(caption)}]
191
+ else
192
+ puts %Q[●リスト#{get_chap}.#{@chapter.list(id).number} #{compile_inline(caption)}]
193
+ end
194
+ end
195
+
196
+ def list_body(id, lines)
197
+ lines.each do |line|
198
+ puts detab(line)
199
+ end
200
+ puts "◆/list◆"
201
+ end
202
+
203
+ def listnum_body(lines)
204
+ lines.each_with_index do |line, i|
205
+ puts detab((i+1).to_s.rjust(2) + " " +line)
206
+ end
207
+ puts "◆/list◆"
208
+ end
209
+
210
+ def emlist(lines, caption=nil)
211
+ puts "◆list/◆"
212
+ puts %Q[●#{compile_inline(caption)}] unless caption.nil?
213
+ lines.each do |line|
214
+ puts detab(line)
215
+ end
216
+ puts "◆/list◆"
217
+ end
218
+
219
+ # o1,o2のようなことはできない
220
+
221
+ def inline_balloon(str)
222
+ "◆comment/◆#{str}◆/comment◆"
223
+ end
224
+
225
+ def inline_comment(str)
226
+ inline_balloon(str)
227
+ end
228
+
229
+ # whiteリスト代用
230
+ def cmd(lines, caption=nil)
231
+ puts "◆list-white/◆"
232
+ puts %Q[●#{compile_inline(caption)}] unless caption.nil?
233
+ lines.each do |line|
234
+ puts detab(line)
235
+ end
236
+ puts "◆/list-white◆"
237
+ end
238
+
239
+ def inline_img(id)
240
+ chapter, id = extract_chapter_id(id)
241
+ if get_chap(chapter).nil?
242
+ "図#{chapter.image(id).number}"
243
+ else
244
+ "図#{get_chap(chapter)}.#{chapter.image(id).number}"
245
+ end
246
+ end
247
+
248
+ def image(lines, id, caption, metric=nil)
249
+ if get_chap.nil?
250
+ puts "●図#{@chapter.image(id).number} #{compile_inline(caption)}"
251
+ else
252
+ puts "●図#{get_chap}.#{@chapter.image(id).number} #{compile_inline(caption)}"
253
+ end
254
+ if @chapter.image(id).bound?
255
+ puts @chapter.image(id).path
256
+ else
257
+ lines.each do |line|
258
+ puts line
259
+ end
260
+ end
261
+ end
262
+
263
+ def inline_table(id)
264
+ chapter, id = extract_chapter_id(id)
265
+ if get_chap(chapter).nil?
266
+ "表#{chapter.table(id).number}"
267
+ else
268
+ "表#{get_chap(chapter)}.#{chapter.table(id).number}"
269
+ end
270
+ end
271
+
272
+ def table(lines, id = nil, caption = nil)
273
+ rows = []
274
+ sepidx = nil
275
+ lines.each_with_index do |line, idx|
276
+ if /\A[\=\-]{12}/ =~ line
277
+ # just ignore
278
+ #error "too many table separator" if sepidx
279
+ sepidx ||= idx
280
+ next
281
+ end
282
+ rows.push line.strip.split(/\t+/).map {|s| s.sub(/\A\./, '') }
283
+ end
284
+ rows = adjust_n_cols(rows)
285
+
286
+ puts "◆table/◆"
287
+ begin
288
+ table_header id, caption unless caption.nil?
289
+ rescue KeyError => err
290
+ error "no such table: #{id}"
291
+ end
292
+ return if rows.empty?
293
+ table_begin rows.first.size
294
+ if sepidx
295
+ sepidx.times do
296
+ print "◆table-title◆"
297
+ tr rows.shift.map {|s| th(s) }
298
+ end
299
+ rows.each do |cols|
300
+ tr cols.map {|s| td(s) }
301
+ end
302
+ else
303
+ rows.each do |cols|
304
+ h, *cs = *cols
305
+ tr [th(h)] + cs.map {|s| td(s) }
306
+ end
307
+ end
308
+ table_end
309
+ end
310
+
311
+ def table_header(id, caption)
312
+ if get_chap.nil?
313
+ puts "●表#{@chapter.table(id).number} #{compile_inline(caption)}"
314
+ else
315
+ puts "●表#{get_chap}.#{@chapter.table(id).number} #{compile_inline(caption)}"
316
+ end
317
+ end
318
+
319
+ def table_begin(ncols)
320
+ end
321
+
322
+ def tr(rows)
323
+ puts rows.join("\t")
324
+ end
325
+
326
+ def th(str)
327
+ str
328
+ end
329
+
330
+ def td(str)
331
+ str
332
+ end
333
+
334
+ def table_end
335
+ puts "◆/table◆"
336
+ end
337
+
338
+ def inline_raw(str)
339
+ %Q[#{super(str).gsub("\\n", "\n")}]
340
+ end
341
+
342
+ def inline_uchar(str)
343
+ [str.to_i(16)].pack("U")
344
+ end
345
+
346
+ def text(str)
347
+ str
348
+ end
349
+
350
+ def nofunc_text(str)
351
+ str
352
+ end
353
+ end
354
+
355
+ end # module ReVIEW