review 2.0.0.beta1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +66 -1
  3. data/.rubocop_todo.yml +617 -0
  4. data/.travis.yml +16 -1
  5. data/ChangeLog +48 -0
  6. data/Dockerfile +22 -0
  7. data/Gemfile +0 -1
  8. data/README.md +97 -0
  9. data/Rakefile +10 -11
  10. data/appveyor.yml +9 -0
  11. data/bin/review +46 -0
  12. data/bin/review-check +8 -21
  13. data/bin/review-compile +26 -43
  14. data/bin/review-index +9 -22
  15. data/bin/review-init +21 -25
  16. data/bin/review-preproc +9 -13
  17. data/bin/review-validate +1 -1
  18. data/bin/review-vol +3 -17
  19. data/bin/review-webmaker +15 -0
  20. data/doc/NEWS.ja.md +534 -0
  21. data/doc/NEWS.md +538 -0
  22. data/doc/catalog.ja.md +10 -18
  23. data/doc/catalog.md +5 -9
  24. data/doc/config.yml.sample +319 -0
  25. data/doc/customize_epub.ja.md +42 -0
  26. data/doc/format.ja.md +320 -288
  27. data/doc/format.md +277 -170
  28. data/doc/format_idg.ja.md +82 -175
  29. data/doc/pdfmaker.ja.md +61 -0
  30. data/doc/pdfmaker.md +65 -0
  31. data/doc/quickstart.ja.md +88 -98
  32. data/doc/quickstart.md +72 -110
  33. data/doc/sample.css +41 -0
  34. data/doc/writing_vertical.ja.md +55 -0
  35. data/doc/writing_vertical.md +5 -0
  36. data/lib/epubmaker/content.rb +3 -3
  37. data/lib/epubmaker/epubcommon.rb +173 -145
  38. data/lib/epubmaker/epubv2.rb +24 -77
  39. data/lib/epubmaker/epubv3.rb +72 -73
  40. data/lib/epubmaker/producer.rb +54 -30
  41. data/lib/lineinput.rb +48 -0
  42. data/lib/review/book.rb +0 -1
  43. data/lib/review/book/base.rb +47 -27
  44. data/lib/review/book/chapter.rb +48 -19
  45. data/lib/review/book/compilable.rb +10 -14
  46. data/lib/review/book/index.rb +10 -19
  47. data/lib/review/book/page_metric.rb +0 -10
  48. data/lib/review/book/part.rb +17 -3
  49. data/lib/review/builder.rb +84 -68
  50. data/lib/review/catalog.rb +5 -1
  51. data/lib/review/compiler.rb +327 -4657
  52. data/lib/review/configure.rb +84 -10
  53. data/lib/review/converter.rb +28 -0
  54. data/lib/review/epubbuilder.rb +1 -1
  55. data/lib/review/epubmaker.rb +142 -158
  56. data/lib/review/ewbbuilder.rb +5 -5
  57. data/lib/review/exception.rb +1 -1
  58. data/lib/review/extentions.rb +1 -1
  59. data/lib/review/extentions/hash.rb +15 -0
  60. data/lib/review/extentions/string.rb +2 -1
  61. data/lib/review/htmlbuilder.rb +364 -348
  62. data/lib/review/htmltoc.rb +44 -0
  63. data/lib/review/htmlutils.rb +12 -6
  64. data/lib/review/i18n.rb +78 -6
  65. data/lib/review/i18n.yml +7 -4
  66. data/lib/review/idgxmlbuilder.rb +226 -267
  67. data/lib/review/latexbuilder.rb +281 -274
  68. data/lib/review/latexutils.rb +56 -49
  69. data/lib/review/makerhelper.rb +8 -4
  70. data/lib/review/markdownbuilder.rb +80 -124
  71. data/lib/review/pdfmaker.rb +197 -138
  72. data/lib/review/preprocessor.rb +16 -67
  73. data/lib/review/template.rb +24 -0
  74. data/lib/review/textbuilder.rb +1 -1
  75. data/lib/review/textutils.rb +18 -24
  76. data/lib/review/tocparser.rb +51 -106
  77. data/lib/review/tocprinter.rb +61 -117
  78. data/lib/review/topbuilder.rb +119 -126
  79. data/lib/review/unfold.rb +2 -2
  80. data/lib/review/version.rb +1 -1
  81. data/lib/review/webmaker.rb +302 -0
  82. data/lib/review/webtocprinter.rb +48 -0
  83. data/lib/review/yamlloader.rb +47 -0
  84. data/review.gemspec +3 -3
  85. data/templates/html/layout-html5.html.erb +17 -0
  86. data/templates/html/layout-xhtml1.html.erb +20 -0
  87. data/{lib/review → templates/latex}/layout.tex.erb +107 -115
  88. data/templates/ncx/epubv2.ncx.erb +11 -0
  89. data/templates/opf/epubv2.opf.erb +21 -0
  90. data/templates/opf/epubv3.opf.erb +18 -0
  91. data/templates/web/html/layout-html5.html.erb +56 -0
  92. data/templates/web/html/layout-xhtml1.html.erb +20 -0
  93. data/templates/xml/container.xml.erb +6 -0
  94. data/test/assets/test.xml.erb +3 -0
  95. data/test/assets/test_template.tex +28 -71
  96. data/test/assets/test_template_backmatter.tex +1 -9
  97. data/test/sample-book/src/Rakefile +12 -3
  98. data/{doc/sample.yml → test/sample-book/src/config-epub2.yml} +92 -147
  99. data/test/sample-book/src/config.yml +40 -154
  100. data/test/sample-book/src/style-web.css +45 -0
  101. data/test/sample-book/src/style.css +23 -1
  102. data/test/test.re +1 -1
  103. data/test/test_book.rb +15 -17
  104. data/test/test_book_chapter.rb +2 -80
  105. data/test/test_book_part.rb +1 -1
  106. data/test/test_builder.rb +28 -6
  107. data/test/test_catalog.rb +17 -0
  108. data/test/test_compiler.rb +14 -59
  109. data/test/test_configure.rb +94 -0
  110. data/test/test_converter.rb +21 -0
  111. data/test/test_epub3maker.rb +155 -3
  112. data/test/test_epubmaker.rb +245 -30
  113. data/test/test_epubmaker_cmd.rb +2 -2
  114. data/test/test_extentions_hash.rb +60 -0
  115. data/test/test_helper.rb +4 -47
  116. data/test/test_htmlbuilder.rb +282 -175
  117. data/test/test_htmltoc.rb +33 -0
  118. data/test/test_i18n.rb +134 -70
  119. data/test/test_idgxmlbuilder.rb +58 -39
  120. data/test/test_latexbuilder.rb +132 -14
  121. data/test/test_lineinput.rb +5 -26
  122. data/test/test_makerhelper.rb +6 -4
  123. data/test/test_markdownbuilder.rb +23 -5
  124. data/test/test_pdfmaker.rb +86 -20
  125. data/test/test_pdfmaker_cmd.rb +1 -3
  126. data/test/test_review_ext.rb +1 -1
  127. data/test/test_template.rb +27 -0
  128. data/test/test_textutils.rb +36 -0
  129. data/test/test_tocparser.rb +25 -0
  130. data/test/test_topbuilder.rb +34 -2
  131. data/test/test_yamlloader.rb +188 -0
  132. metadata +71 -29
  133. data/README.rdoc +0 -81
  134. data/bin/review-epubmaker-legacy +0 -1024
  135. data/doc/ruby-uuid/README +0 -11
  136. data/doc/ruby-uuid/README.ja +0 -34
  137. data/lib/review/compiler/literals_1_8.kpeg +0 -19
  138. data/lib/review/compiler/literals_1_8.rb +0 -432
  139. data/lib/review/compiler/literals_1_9.kpeg +0 -22
  140. data/lib/review/compiler/literals_1_9.rb +0 -435
  141. data/lib/review/extentions/array.rb +0 -25
  142. data/lib/review/htmllayout.rb +0 -41
  143. data/lib/review/inaobuilder.rb +0 -357
  144. data/lib/review/location.rb +0 -24
  145. data/lib/review/node.rb +0 -267
  146. data/lib/review/review.kpeg +0 -724
  147. data/lib/uuid.rb +0 -312
  148. data/rubocop-todo.yml +0 -456
  149. data/test/test_inaobuilder.rb +0 -247
  150. data/test/test_uuid.rb +0 -157
@@ -34,7 +34,7 @@ module ReVIEW
34
34
  # }
35
35
 
36
36
  def emlist(lines, caption = nil)
37
- firstline = f.lineno
37
+ # firstline = f.lineno
38
38
  puts
39
39
  puts caption
40
40
  puts '//lst1'
@@ -62,7 +62,7 @@ module ReVIEW
62
62
  lines.each do |line|
63
63
  if noescape
64
64
  puts detab(line)
65
- elsif /\AC:.*?>(.+)/ =~ line # DOS prompt hack
65
+ elsif /\AC:.*?>(.+)/ =~ line # DOS prompt hack
66
66
  prompt, cmd = *line.split('>', 2)
67
67
  puts "#{escape(prompt)}>//command{#{escape(cmd)}}//}"
68
68
  else
@@ -198,7 +198,7 @@ module ReVIEW
198
198
  # FIXME
199
199
  end
200
200
 
201
- Z_SPACE = "\241\241" # zen-kaku space in EUC-JP
201
+ Z_SPACE = "\241\241" # zen-kaku space in EUC-JP
202
202
 
203
203
  def paragraph(lines)
204
204
  if @noindent
@@ -263,10 +263,10 @@ module ReVIEW
263
263
  if abbr
264
264
  add_index(word) + "//g{#{word}//}" +
265
265
  add_index(abbr) + "(#{abbr}, " +
266
- add_index(eng) + "#{eng})"
266
+ add_index(eng) + "#{eng})"
267
267
  elsif eng
268
268
  add_index(word) + "//g{#{word}//}" +
269
- add_index(eng) + "(#{eng})"
269
+ add_index(eng) + "(#{eng})"
270
270
  else
271
271
  add_index(word) + "//g{#{word}//}"
272
272
  end
@@ -17,5 +17,5 @@ module ReVIEW
17
17
  class CompileError < ApplicationError; end
18
18
  class SyntaxError < CompileError; end
19
19
  class FileNotFound < ApplicationError; end
20
- class KeyError < CompileError; end
20
+ class KeyError < CompileError; end
21
21
  end
@@ -1,4 +1,4 @@
1
1
  require 'review/extentions/object'
2
2
  require 'review/extentions/string'
3
- require 'review/extentions/array'
3
+ require 'review/extentions/hash'
4
4
 
@@ -0,0 +1,15 @@
1
+ class Hash
2
+ def deep_merge!(other)
3
+ self.merge!(other) do |key, v_self, v_other|
4
+ if v_self.kind_of?(Hash) && v_other.kind_of?(Hash)
5
+ v_self.deep_merge(v_other)
6
+ else
7
+ v_other
8
+ end
9
+ end
10
+ end
11
+
12
+ def deep_merge(other)
13
+ self.dup.deep_merge!(other)
14
+ end
15
+ end
@@ -1,4 +1,5 @@
1
- if defined?(Encoding) && Encoding.respond_to?("default_external")
1
+ if defined?(Encoding) && Encoding.respond_to?("default_external") &&
2
+ Encoding.default_external != Encoding::UTF_8
2
3
  Encoding.default_external = "UTF-8"
3
4
  end
4
5
 
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
  #
3
3
  # Copyright (c) 2002-2007 Minero Aoki
4
- # 2008-2014 Minero Aoki, Kenshi Muto, Masayoshi Takahashi,
4
+ # 2008-2016 Minero Aoki, Kenshi Muto, Masayoshi Takahashi,
5
5
  # KADO Masanori
6
6
  #
7
7
  # This program is free software.
@@ -11,8 +11,9 @@
11
11
 
12
12
  require 'review/builder'
13
13
  require 'review/htmlutils'
14
- require 'review/htmllayout'
14
+ require 'review/template'
15
15
  require 'review/textutils'
16
+ require 'review/webtocprinter'
16
17
 
17
18
  module ReVIEW
18
19
 
@@ -22,18 +23,19 @@ module ReVIEW
22
23
  include HTMLUtils
23
24
 
24
25
  [:ref].each {|e| Compiler.definline(e) }
25
- Compiler.defblock(:memo, 0..1)
26
- Compiler.defblock(:tip, 0..1)
27
- Compiler.defblock(:info, 0..1)
28
26
  Compiler.defblock(:planning, 0..1)
29
27
  Compiler.defblock(:best, 0..1)
30
- Compiler.defblock(:important, 0..1)
31
28
  Compiler.defblock(:security, 0..1)
32
- Compiler.defblock(:caution, 0..1)
33
- Compiler.defblock(:notice, 0..1)
34
29
  Compiler.defblock(:point, 0..1)
35
30
  Compiler.defblock(:shoot, 0..1)
36
31
 
32
+ def pre_paragraph
33
+ '<p>'
34
+ end
35
+ def post_paragraph
36
+ '</p>'
37
+ end
38
+
37
39
  def extname
38
40
  ".#{@book.config["htmlext"]}"
39
41
  end
@@ -51,87 +53,57 @@ module ReVIEW
51
53
  @chapter.book.image_types = %w( .png .jpg .jpeg .gif .svg )
52
54
  @column = 0
53
55
  @sec_counter = SecCounter.new(5, @chapter)
56
+ @nonum_counter = 0
57
+ @body_ext = nil
58
+ @toc = nil
54
59
  end
55
60
  private :builder_init_file
56
61
 
57
62
  def result
58
- layout_file = File.join(@book.basedir, "layouts", "layout.html.erb")
59
- unless File.exist?(layout_file) # backward compatibility
60
- layout_file = File.join(@book.basedir, "layouts", "layout.erb")
63
+ if @book.config.maker == "webmaker"
64
+ htmldir = "web/html"
65
+ localfilename = "layout-web.html.erb"
66
+ else
67
+ htmldir = "html"
68
+ localfilename = "layout.html.erb"
69
+ end
70
+ if @book.htmlversion == 5
71
+ htmlfilename = File.join(htmldir, "layout-html5.html.erb")
72
+ else
73
+ htmlfilename = File.join(htmldir, "layout-xhtml1.html.erb")
74
+ end
75
+
76
+ layout_file = File.join(@book.basedir, "layouts", localfilename)
77
+ if !File.exist?(layout_file) && File.exist?(File.join(@book.basedir, "layouts", "layout.erb"))
78
+ raise ReVIEW::ConfigError, "layout.erb is obsoleted. Please use layout.html.erb."
61
79
  end
62
80
  if File.exist?(layout_file)
63
81
  if ENV["REVIEW_SAFE_MODE"].to_i & 4 > 0
64
82
  warn "user's layout is prohibited in safe mode. ignored."
65
- else
66
- title = convert_outencoding(strip_html(@chapter.title), @book.config["outencoding"])
67
-
68
- toc = ""
69
- toc_level = 0
70
- @chapter.headline_index.items.each do |i|
71
- caption = "<li>#{strip_html(i.caption)}</li>\n"
72
- if toc_level == i.number.size
73
- # do nothing
74
- elsif toc_level < i.number.size
75
- toc += "<ul>\n" * (i.number.size - toc_level)
76
- toc_level = i.number.size
77
- elsif toc_level > i.number.size
78
- toc += "</ul>\n" * (toc_level - i.number.size)
79
- toc_level = i.number.size
80
- toc += "<ul>\n" * (toc_level - 1)
81
- end
82
- toc += caption
83
- end
84
- toc += "</ul>" * toc_level
85
-
86
- return messages() +
87
- HTMLLayout.new(
88
- {'body' => @output.string, 'title' => title, 'toc' => toc,
89
- 'builder' => self,
90
- 'next' => @chapter.next_chapter,
91
- 'prev' => @chapter.prev_chapter},
92
- layout_file).result
83
+ layout_file = File.expand_path(htmlfilename, ReVIEW::Template::TEMPLATE_DIR)
93
84
  end
85
+ else
86
+ layout_file = File.expand_path(htmlfilename, ReVIEW::Template::TEMPLATE_DIR)
94
87
  end
95
88
 
96
89
  # default XHTML header/footer
97
- header = <<EOT
98
- <?xml version="1.0" encoding="#{@book.config["outencoding"] || "UTF-8"}"?>
99
- EOT
100
- if @book.config["htmlversion"].to_i == 5
101
- header += <<EOT
102
- <!DOCTYPE html>
103
- <html xmlns="http://www.w3.org/1999/xhtml" xmlns:#{xmlns_ops_prefix}="http://www.idpf.org/2007/ops" xml:lang="#{@book.config["language"]}">
104
- <head>
105
- <meta charset="#{@book.config["outencoding"] || "UTF-8"}" />
106
- EOT
107
- else
108
- header += <<EOT
109
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
110
- <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ops="http://www.idpf.org/2007/ops" xml:lang="#{@book.config["language"]}">
111
- <head>
112
- <meta http-equiv="Content-Type" content="text/html;charset=#{@book.config["outencoding"] || "UTF-8"}" />
113
- <meta http-equiv="Content-Style-Type" content="text/css" />
114
- EOT
115
- end
116
-
117
- unless @book.config["stylesheet"].nil?
118
- @book.config["stylesheet"].each do |style|
119
- header += <<EOT
120
- <link rel="stylesheet" type="text/css" href="#{style}" />
121
- EOT
122
- end
90
+ @error_messages = error_messages
91
+ @warning_messages = warning_messages
92
+ @title = strip_html(compile_inline(@chapter.title))
93
+ @body = @output.string
94
+ @language = @book.config['language']
95
+ @stylesheets = @book.config["stylesheet"]
96
+ @next = @chapter.next_chapter
97
+ @prev = @chapter.prev_chapter
98
+ @next_title = @next ? compile_inline(@next.title) : ""
99
+ @prev_title = @prev ? compile_inline(@prev.title) : ""
100
+
101
+ if @book.config.maker == "webmaker"
102
+ @toc = ReVIEW::WEBTOCPrinter.book_to_string(@book)
123
103
  end
124
- header += <<EOT
125
- <meta name="generator" content="Re:VIEW" />
126
- <title>#{convert_outencoding(strip_html(@chapter.title), @book.config["outencoding"])}</title>
127
- </head>
128
- <body>
129
- EOT
130
- footer = <<EOT
131
- </body>
132
- </html>
133
- EOT
134
- header + messages() + convert_outencoding(@output.string, @book.config["outencoding"]) + footer
104
+
105
+ tmpl = ReVIEW::Template.load(layout_file)
106
+ tmpl.result(binding)
135
107
  end
136
108
 
137
109
  def xmlns_ops_prefix
@@ -170,7 +142,7 @@ EOT
170
142
  "<ul>\n" +
171
143
  @errors.map {|file, line, msg|
172
144
  "<li>#{escape_html(file)}:#{line}: #{escape_html(msg.to_s)}</li>\n"
173
- }.join('') +
145
+ }.join('') +
174
146
  "</ul>\n"
175
147
  end
176
148
 
@@ -185,94 +157,122 @@ EOT
185
157
  end
186
158
 
187
159
  def headline(level, label, caption)
188
- buf = ""
189
160
  prefix, anchor = headline_prefix(level)
190
161
  unless prefix.nil?
191
162
  prefix = %Q[<span class="secno">#{prefix}</span>]
192
163
  end
164
+ puts '' if level > 1
193
165
  a_id = ""
194
166
  unless anchor.nil?
195
167
  a_id = %Q[<a id="h#{anchor}"></a>]
196
168
  end
197
169
  if caption.empty?
198
- buf << a_id+"\n" unless label.nil?
170
+ puts a_id unless label.nil?
199
171
  else
200
172
  if label.nil?
201
- buf << %Q[<h#{level}>#{a_id}#{prefix}#{caption}</h#{level}>\n]
173
+ puts %Q[<h#{level}>#{a_id}#{prefix}#{compile_inline(caption)}</h#{level}>]
202
174
  else
203
- buf << %Q[<h#{level} id="#{normalize_id(label)}">#{a_id}#{prefix}#{caption}</h#{level}>\n]
175
+ puts %Q[<h#{level} id="#{normalize_id(label)}">#{a_id}#{prefix}#{compile_inline(caption)}</h#{level}>]
204
176
  end
205
177
  end
206
- buf
207
178
  end
208
179
 
209
180
  def nonum_begin(level, label, caption)
210
- buf = ""
211
- buf << "\n" if level > 1
181
+ @nonum_counter += 1
182
+ puts '' if level > 1
212
183
  unless caption.empty?
213
184
  if label.nil?
214
- buf << %Q[<h#{level}>#{caption}</h#{level}>\n]
185
+ id = normalize_id("#{@chapter.name}_nonum#{@nonum_counter}")
186
+ puts %Q[<h#{level} id="#{id}">#{compile_inline(caption)}</h#{level}>]
215
187
  else
216
- buf << %Q[<h#{level} id="#{normalize_id(label)}">#{caption}</h#{level}>\n]
188
+ puts %Q[<h#{level} id="#{normalize_id(label)}">#{compile_inline(caption)}</h#{level}>]
217
189
  end
218
190
  end
219
- buf
220
191
  end
221
192
 
222
193
  def nonum_end(level)
223
194
  end
224
195
 
196
+ def notoc_begin(level, label, caption)
197
+ @nonum_counter += 1
198
+ puts '' if level > 1
199
+ unless caption.empty?
200
+ if label.nil?
201
+ id = normalize_id("#{@chapter.name}_nonum#{@nonum_counter}")
202
+ puts %Q[<h#{level} id="#{id}" notoc="true">#{compile_inline(caption)}</h#{level}>]
203
+ else
204
+ puts %Q[<h#{level} id="#{normalize_id(label)}" notoc="true">#{compile_inline(caption)}</h#{level}>]
205
+ end
206
+ end
207
+ end
208
+
209
+ def notoc_end(level)
210
+ end
211
+
212
+ def nodisp_begin(level, label, caption)
213
+ @nonum_counter += 1
214
+ puts '' if level > 1
215
+ unless caption.empty?
216
+ if label.nil?
217
+ id = normalize_id("#{@chapter.name}_nonum#{@nonum_counter}")
218
+ puts %Q[<a id="#{id}" /><h#{level} id="#{id}" hidden="true">#{compile_inline(caption)}</h#{level}>]
219
+ else
220
+ puts %Q[<a id="#{normalize_id(label)}" /><h#{level} id="#{normalize_id(label)}" hidden="true">#{compile_inline(caption)}</h#{level}>]
221
+ end
222
+ end
223
+ end
224
+
225
+ def nodisp_end(level)
226
+ end
227
+
225
228
  def column_begin(level, label, caption)
226
- buf = %Q[<div class="column">\n]
229
+ puts %Q[<div class="column">]
227
230
 
228
231
  @column += 1
229
- buf << "\n" if level > 1
232
+ puts '' if level > 1
230
233
  a_id = %Q[<a id="column-#{@column}"></a>]
231
234
 
232
235
  if caption.empty?
233
- buf << a_id + "\n" unless label.nil?
236
+ puts a_id unless label.nil?
234
237
  else
235
238
  if label.nil?
236
- buf << %Q[<h#{level}>#{a_id}#{caption}</h#{level}>\n]
239
+ puts %Q[<h#{level}>#{a_id}#{compile_inline(caption)}</h#{level}>]
237
240
  else
238
- buf << %Q[<h#{level} id="#{normalize_id(label)}">#{a_id}#{caption}</h#{level}>\n]
241
+ puts %Q[<h#{level} id="#{normalize_id(label)}">#{a_id}#{compile_inline(caption)}</h#{level}>]
239
242
  end
240
243
  end
241
- buf
244
+ # headline(level, label, caption)
242
245
  end
243
246
 
244
247
  def column_end(level)
245
- "</div>\n"
248
+ puts '</div>'
246
249
  end
247
250
 
248
251
  def xcolumn_begin(level, label, caption)
249
- buf << %Q[<div class="xcolumn">\n]
250
- buf << headline(level, label, caption)
251
- buf
252
+ puts %Q[<div class="xcolumn">]
253
+ headline(level, label, caption)
252
254
  end
253
255
 
254
256
  def xcolumn_end(level)
255
- "</div>\n"
257
+ puts '</div>'
256
258
  end
257
259
 
258
260
  def ref_begin(level, label, caption)
259
- buf << %Q[<div class="reference">\n]
260
- buf << headline(level, label, caption)
261
- buf
261
+ print %Q[<div class="reference">]
262
+ headline(level, label, caption)
262
263
  end
263
264
 
264
265
  def ref_end(level)
265
- "</div>\n"
266
+ puts '</div>'
266
267
  end
267
268
 
268
269
  def sup_begin(level, label, caption)
269
- buf << %Q[<div class="supplement">\n]
270
- buf << headline(level, label, caption)
271
- buf
270
+ print %Q[<div class="supplement">]
271
+ headline(level, label, caption)
272
272
  end
273
273
 
274
274
  def sup_end(level)
275
- "</div>\n"
275
+ puts '</div>'
276
276
  end
277
277
 
278
278
  def tsize(str)
@@ -280,17 +280,13 @@ EOT
280
280
  end
281
281
 
282
282
  def captionblock(type, lines, caption)
283
- buf = %Q[<div class="#{type}">\n]
283
+ puts %Q[<div class="#{type}">]
284
284
  unless caption.nil?
285
- buf << %Q[<p class="caption">#{caption}</p>\n]
285
+ puts %Q[<p class="caption">#{compile_inline(caption)}</p>]
286
286
  end
287
- if @book.config["deprecated-blocklines"].nil?
288
- buf << lines.join("")
289
- else
290
- error "deprecated-blocklines is obsoleted."
291
- end
292
- buf << "</div>\n"
293
- buf
287
+ blocked_lines = split_paragraph(lines)
288
+ puts blocked_lines.join("\n")
289
+ puts '</div>'
294
290
  end
295
291
 
296
292
  def memo(lines, caption = nil)
@@ -329,6 +325,10 @@ EOT
329
325
  captionblock("notice", lines, caption)
330
326
  end
331
327
 
328
+ def warning(lines, caption = nil)
329
+ captionblock("warning", lines, caption)
330
+ end
331
+
332
332
  def point(lines, caption = nil)
333
333
  captionblock("point", lines, caption)
334
334
  end
@@ -338,14 +338,12 @@ EOT
338
338
  end
339
339
 
340
340
  def box(lines, caption = nil)
341
- buf = ""
342
- buf << %Q[<div class="syntax">\n]
343
- buf << %Q[<p class="caption">#{caption}</p>\n] unless caption.nil?
344
- buf << %Q[<pre class="syntax">]
345
- lines.each {|line| buf << detab(line) << "\n" }
346
- buf << "</pre>\n"
347
- buf << "</div>\n"
348
- buf
341
+ puts %Q[<div class="syntax">]
342
+ puts %Q[<p class="caption">#{compile_inline(caption)}</p>] unless caption.nil?
343
+ print %Q[<pre class="syntax">]
344
+ lines.each {|line| puts detab(line) }
345
+ puts '</pre>'
346
+ puts '</div>'
349
347
  end
350
348
 
351
349
  def note(lines, caption = nil)
@@ -353,300 +351,296 @@ EOT
353
351
  end
354
352
 
355
353
  def ul_begin
356
- "<ul>\n"
354
+ puts '<ul>'
357
355
  end
358
356
 
359
357
  def ul_item(lines)
360
- "<li>#{lines.map(&:to_s).join}</li>\n"
358
+ puts "<li>#{lines.join}</li>"
361
359
  end
362
360
 
363
361
  def ul_item_begin(lines)
364
- "<li>#{lines.map(&:to_s).join}"
362
+ print "<li>#{lines.join}"
365
363
  end
366
364
 
367
365
  def ul_item_end
368
- "</li>\n"
366
+ puts "</li>"
369
367
  end
370
368
 
371
369
  def ul_end
372
- "</ul>\n"
370
+ puts '</ul>'
373
371
  end
374
372
 
375
373
  def ol_begin
376
374
  if @ol_num
377
- num = @ol_num
375
+ puts "<ol start=\"#{@ol_num}\">" ## it's OK in HTML5, but not OK in XHTML1.1
378
376
  @ol_num = nil
379
- "<ol start=\"#{num}\">\n" ## it's OK in HTML5, but not OK in XHTML1.1
380
377
  else
381
- "<ol>\n"
378
+ puts '<ol>'
382
379
  end
383
380
  end
384
381
 
385
382
  def ol_item(lines, num)
386
- "<li>#{lines.map(&:to_s).join}</li>\n"
383
+ puts "<li>#{lines.join}</li>"
387
384
  end
388
385
 
389
386
  def ol_end
390
- "</ol>\n"
387
+ puts '</ol>'
391
388
  end
392
389
 
393
390
  def dl_begin
394
- "<dl>\n"
391
+ puts '<dl>'
395
392
  end
396
393
 
397
394
  def dt(line)
398
- "<dt>#{line}</dt>\n"
395
+ puts "<dt>#{line}</dt>"
399
396
  end
400
397
 
401
398
  def dd(lines)
402
- "<dd>#{lines.join}</dd>\n"
399
+ puts "<dd>#{lines.join}</dd>"
403
400
  end
404
401
 
405
402
  def dl_end
406
- "</dl>\n"
403
+ puts '</dl>'
407
404
  end
408
405
 
409
406
  def paragraph(lines)
410
407
  if @noindent.nil?
411
- "<p>#{lines.join}</p>\n"
408
+ puts "<p>#{lines.join}</p>"
412
409
  else
410
+ puts %Q[<p class="noindent">#{lines.join}</p>]
413
411
  @noindent = nil
414
- %Q[<p class="noindent">#{lines.join}</p>\n]
415
412
  end
416
413
  end
417
414
 
418
- def parasep()
419
- "<br />\n"
415
+ def parasep
416
+ puts '<br />'
420
417
  end
421
418
 
422
419
  def read(lines)
423
- if @book.config["deprecated-blocklines"].nil?
424
- %Q[<div class="lead">\n#{lines.join("")}\n</div>\n]
425
- else
426
- error "deprecated-blocklines is obsoleted."
427
- end
420
+ blocked_lines = split_paragraph(lines)
421
+ puts %Q[<div class="lead">\n#{blocked_lines.join("\n")}\n</div>]
428
422
  end
429
423
 
430
424
  alias_method :lead, :read
431
425
 
432
426
  def list(lines, id, caption, lang = nil)
433
- buf = %Q[<div class="caption-code">\n]
427
+ puts %Q[<div class="caption-code">]
434
428
  begin
435
- buf << list_header(id, caption, lang)
429
+ list_header id, caption, lang
436
430
  rescue KeyError
437
431
  error "no such list: #{id}"
438
432
  end
439
- buf << list_body(id, lines, lang)
440
- buf << "</div>\n"
441
- buf
433
+ list_body id, lines, lang
434
+ puts '</div>'
442
435
  end
443
436
 
444
437
  def list_header(id, caption, lang)
445
438
  if get_chap.nil?
446
- %Q[<p class="caption">#{I18n.t("list")}#{I18n.t("format_number_header_without_chapter", [@chapter.list(id).number])}#{I18n.t("caption_prefix")}#{caption}</p>\n]
439
+ puts %Q[<p class="caption">#{I18n.t("list")}#{I18n.t("format_number_header_without_chapter", [@chapter.list(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}</p>]
447
440
  else
448
- %Q[<p class="caption">#{I18n.t("list")}#{I18n.t("format_number_header", [get_chap, @chapter.list(id).number])}#{I18n.t("caption_prefix")}#{caption}</p>\n]
441
+ puts %Q[<p class="caption">#{I18n.t("list")}#{I18n.t("format_number_header", [get_chap, @chapter.list(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}</p>]
449
442
  end
450
443
  end
451
444
 
452
445
  def list_body(id, lines, lang)
453
446
  id ||= ''
454
- buf = %Q[<pre class="list">]
447
+ print %Q[<pre class="list">]
455
448
  body = lines.inject(''){|i, j| i + detab(j) + "\n"}
456
449
  lexer = lang || File.extname(id).gsub(/\./, '')
457
- buf << highlight(:body => body, :lexer => lexer, :format => 'html')
458
- buf << "</pre>\n"
459
- buf
450
+ puts highlight(:body => body, :lexer => lexer, :format => 'html')
451
+ puts '</pre>'
460
452
  end
461
453
 
462
- def source(lines, caption = nil)
463
- buf = %Q[<div class="source-code">\n]
464
- buf << source_header(caption)
465
- buf << source_body(caption, lines)
466
- buf << "</div>\n"
467
- buf
454
+ def source(lines, caption = nil, lang = nil)
455
+ puts %Q[<div class="source-code">]
456
+ source_header caption
457
+ source_body caption, lines, lang
458
+ puts '</div>'
468
459
  end
469
460
 
470
461
  def source_header(caption)
471
462
  if caption.present?
472
- %Q[<p class="caption">#{caption}</p>\n]
463
+ puts %Q[<p class="caption">#{compile_inline(caption)}</p>]
473
464
  end
474
465
  end
475
466
 
476
- def source_body(id, lines)
467
+ def source_body(id, lines, lang)
477
468
  id ||= ''
478
- buf = %Q[<pre class="source">]
469
+ print %Q[<pre class="source">]
479
470
  body = lines.inject(''){|i, j| i + detab(j) + "\n"}
480
- lexer = File.extname(id).gsub(/\./, '')
481
- buf << highlight(:body => body, :lexer => lexer, :format => 'html')
482
- buf << "</pre>\n"
483
- buf
471
+ lexer = lang || File.extname(id).gsub(/\./, '')
472
+ puts highlight(:body => body, :lexer => lexer, :format => 'html')
473
+ puts '</pre>'
484
474
  end
485
475
 
486
476
  def listnum(lines, id, caption, lang = nil)
487
- buf = %Q[<div class="code">\n]
477
+ puts %Q[<div class="code">]
488
478
  begin
489
- buf << list_header(id, caption, lang)
479
+ list_header id, caption, lang
490
480
  rescue KeyError
491
481
  error "no such list: #{id}"
492
482
  end
493
- buf << listnum_body(lines, lang)
494
- buf << "</div>"
495
- buf
483
+ listnum_body lines, lang
484
+ puts '</div>'
496
485
  end
497
486
 
498
487
  def listnum_body(lines, lang)
499
- buf = ""
500
- body = lines.inject(''){|i, j| i + detab(j) + "\n"}
501
- lexer = lang
502
- buf << highlight(:body => body, :lexer => lexer, :format => 'html',
503
- :options => {:linenos => 'inline', :nowrap => false})
504
- buf
488
+ if highlight?
489
+ body = lines.inject(''){|i, j| i + detab(j) + "\n"}
490
+ lexer = lang
491
+ puts highlight(:body => body, :lexer => lexer, :format => 'html',
492
+ :options => {:linenos => 'inline', :nowrap => false})
493
+ else
494
+ print '<pre class="list">'
495
+ lines.each_with_index do |line, i|
496
+ puts detab((i+1).to_s.rjust(2) + ": " + line)
497
+ end
498
+ puts '</pre>'
499
+ end
505
500
  end
506
501
 
507
502
  def emlist(lines, caption = nil, lang = nil)
508
- buf = %Q[<div class="emlist-code">\n]
503
+ puts %Q[<div class="emlist-code">]
509
504
  if caption.present?
510
- buf << %Q(<p class="caption">#{caption}</p>\n)
505
+ puts %Q(<p class="caption">#{compile_inline(caption)}</p>)
511
506
  end
512
- buf << %Q[<pre class="emlist">]
507
+ print %Q[<pre class="emlist">]
513
508
  body = lines.inject(''){|i, j| i + detab(j) + "\n"}
514
509
  lexer = lang
515
- buf << highlight(:body => body, :lexer => lexer, :format => 'html')
516
- buf << "</pre>\n"
517
- buf << "</div>\n"
518
- buf
510
+ puts highlight(:body => body, :lexer => lexer, :format => 'html')
511
+ puts '</pre>'
512
+ puts '</div>'
519
513
  end
520
514
 
521
515
  def emlistnum(lines, caption = nil, lang = nil)
522
- buf = %Q[<div class="emlistnum-code">\n]
516
+ puts %Q[<div class="emlistnum-code">]
523
517
  if caption.present?
524
- buf << %Q(<p class="caption">#{caption}</p>\n)
518
+ puts %Q(<p class="caption">#{compile_inline(caption)}</p>)
525
519
  end
526
- body = lines.inject(''){|i, j| i + detab(j) + "\n"}
527
- lexer = lang
528
- buf << highlight(:body => body, :lexer => lexer, :format => 'html',
529
- :options => {:linenos => 'inline', :nowrap => false})
530
- buf << "</div>\n"
531
- buf
520
+
521
+ if highlight?
522
+ body = lines.inject(''){|i, j| i + detab(j) + "\n"}
523
+ lexer = lang
524
+ puts highlight(:body => body, :lexer => lexer, :format => 'html',
525
+ :options => {:linenos => 'inline', :nowrap => false})
526
+ else
527
+ print '<pre class="emlist">'
528
+ lines.each_with_index do |line, i|
529
+ puts detab((i+1).to_s.rjust(2) + ": " + line)
530
+ end
531
+ puts '</pre>'
532
+ end
533
+
534
+ puts '</div>'
532
535
  end
533
536
 
534
537
  def cmd(lines, caption = nil)
535
- buf = %Q[<div class="cmd-code">\n]
538
+ puts %Q[<div class="cmd-code">]
536
539
  if caption.present?
537
- buf << %Q(<p class="caption">#{caption}</p>\n)
540
+ puts %Q(<p class="caption">#{compile_inline(caption)}</p>)
538
541
  end
539
- buf << %Q[<pre class="cmd">]
542
+ print %Q[<pre class="cmd">]
540
543
  body = lines.inject(''){|i, j| i + detab(j) + "\n"}
541
544
  lexer = 'shell-session'
542
- buf << highlight(:body => body, :lexer => lexer, :format => 'html')
543
- buf << "</pre>\n"
544
- buf << "</div>\n"
545
- buf
545
+ puts highlight(:body => body, :lexer => lexer, :format => 'html')
546
+ puts '</pre>'
547
+ puts '</div>'
546
548
  end
547
549
 
548
550
  def quotedlist(lines, css_class)
549
- buf = %Q[<blockquote><pre class="#{css_class}">\n]
551
+ print %Q[<blockquote><pre class="#{css_class}">]
550
552
  lines.each do |line|
551
- buf << detab(line) << "\n"
553
+ puts detab(line)
552
554
  end
553
- buf << "</pre></blockquote>\n"
555
+ puts '</pre></blockquote>'
554
556
  end
555
557
  private :quotedlist
556
558
 
557
559
  def quote(lines)
558
- if @book.config["deprecated-blocklines"].nil?
559
- "<blockquote>#{lines.join("")}</blockquote>\n"
560
- else
561
- error "deprecated-blocklines is obsoleted."
562
- end
560
+ blocked_lines = split_paragraph(lines)
561
+ puts "<blockquote>#{blocked_lines.join("\n")}</blockquote>"
563
562
  end
564
563
 
565
564
  def doorquote(lines, ref)
566
- buf = ""
567
- if @book.config["deprecated-blocklines"].nil?
568
- buf << %Q[<blockquote style="text-align:right;">\n]
569
- buf << "#{lines.join("")}\n"
570
- buf << %Q[<p>#{ref}より</p>\n]
571
- buf << %Q[</blockquote>\n]
572
- else
573
- error "deprecated-blocklines is obsoleted."
574
- end
575
- buf
565
+ blocked_lines = split_paragraph(lines)
566
+ puts %Q[<blockquote style="text-align:right;">]
567
+ puts "#{blocked_lines.join("\n")}"
568
+ puts %Q[<p>#{ref}より</p>]
569
+ puts %Q[</blockquote>]
576
570
  end
577
571
 
578
572
  def talk(lines)
579
- buf = ""
580
- buf << %Q[<div class="talk">\n]
581
- if @book.config["deprecated-blocklines"].nil?
582
- buf << "#{lines.join("\n")}\n"
583
- else
584
- error "deprecated-blocklines is obsoleted."
585
- end
586
- buf << "</div>\n"
587
- buf
573
+ puts %Q[<div class="talk">]
574
+ blocked_lines = split_paragraph(lines)
575
+ puts "#{blocked_lines.join("\n")}"
576
+ puts '</div>'
588
577
  end
589
578
 
590
579
  def texequation(lines)
591
- buf << %Q[<div class="equation">\n]
580
+ puts %Q[<div class="equation">]
592
581
  if @book.config["mathml"]
593
582
  require 'math_ml'
594
583
  require 'math_ml/symbol/character_reference'
595
584
  p = MathML::LaTeX::Parser.new(:symbol=>MathML::Symbol::CharacterReference)
596
- buf << p.parse(unescape_html(lines.join("\n")), true) << "\n
585
+ puts p.parse(unescape_html(lines.join("\n")), true)
597
586
  else
598
- buf << '<pre>'
599
- buf << "#{lines.join("\n")}\n"
600
- buf << "</pre>\n"
587
+ print '<pre>'
588
+ puts "#{lines.join("\n")}"
589
+ puts '</pre>'
601
590
  end
602
- buf << "</div>\n"
603
- buf
591
+ puts '</div>'
604
592
  end
605
593
 
606
594
  def handle_metric(str)
607
595
  if str =~ /\Ascale=([\d.]+)\Z/
608
- return "width=\"#{($1.to_f * 100).round}%\""
596
+ return {'class' => sprintf("width-%03dper", ($1.to_f * 100).round)}
609
597
  else
610
598
  k, v = str.split('=', 2)
611
- return %Q|#{k}=\"#{v.sub(/\A&quot;/, '').sub(/\A["']/, '').sub(/&quot;\Z/, '').sub(/["']\Z/, '')}\"|
599
+ return {k => v.sub(/\A["']/, '').sub(/["']\Z/, '')}
612
600
  end
613
601
  end
614
602
 
615
603
  def result_metric(array)
616
- " #{array.join(' ')}"
604
+ attrs = {}
605
+ array.each do |item|
606
+ k = item.keys[0]
607
+ if attrs[k]
608
+ attrs[k] << item[k]
609
+ else
610
+ attrs[k] = [item[k]]
611
+ end
612
+ end
613
+ " "+attrs.map{|k, v| %Q|#{k}="#{v.join(' ')}"| }.join(' ')
617
614
  end
618
615
 
619
616
  def image_image(id, caption, metric)
620
617
  metrics = parse_metric("html", metric)
621
- buf = %Q[<div id="#{normalize_id(id)}" class="image">\n]
622
- buf << %Q[<img src="#{@chapter.image(id).path.sub(/\A\.\//, "")}" alt="#{escape_html(caption)}"#{metrics} />\n]
623
- buf << image_header(id, caption)
624
- buf << %Q[</div>\n]
625
- buf
618
+ puts %Q[<div id="#{normalize_id(id)}" class="image">]
619
+ puts %Q[<img src="#{@chapter.image(id).path.sub(/\A\.\//, "")}" alt="#{escape_html(compile_inline(caption))}"#{metrics} />]
620
+ image_header id, caption
621
+ puts %Q[</div>]
626
622
  end
627
623
 
628
624
  def image_dummy(id, caption, lines)
629
- buf = %Q[<div class="image">\n]
630
- buf << %Q[<pre class="dummyimage">\n]
625
+ puts %Q[<div class="image">]
626
+ puts %Q[<pre class="dummyimage">]
631
627
  lines.each do |line|
632
- buf << detab(line) << "\n"
628
+ puts detab(line)
633
629
  end
634
- buf << %Q[</pre>\n]
635
- buf << image_header(id, caption)
636
- buf << %Q[</div>\n]
630
+ puts %Q[</pre>]
631
+ image_header id, caption
632
+ puts %Q[</div>]
637
633
  warn "no such image: #{id}"
638
- buf
639
634
  end
640
635
 
641
636
  def image_header(id, caption)
642
- buf = %Q[<p class="caption">\n]
637
+ puts %Q[<p class="caption">]
643
638
  if get_chap.nil?
644
- buf << %Q[#{I18n.t("image")}#{I18n.t("format_number_header_without_chapter", [@chapter.image(id).number])}#{I18n.t("caption_prefix")}#{caption}\n]
639
+ puts %Q[#{I18n.t("image")}#{I18n.t("format_number_header_without_chapter", [@chapter.image(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}]
645
640
  else
646
- buf << %Q[#{I18n.t("image")}#{I18n.t("format_number_header", [get_chap, @chapter.image(id).number])}#{I18n.t("caption_prefix")}#{caption}\n]
641
+ puts %Q[#{I18n.t("image")}#{I18n.t("format_number_header", [get_chap, @chapter.image(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}]
647
642
  end
648
- buf << %Q[</p>\n]
649
- buf
643
+ puts %Q[</p>]
650
644
  end
651
645
 
652
646
  def table(lines, id = nil, caption = nil)
@@ -664,49 +658,48 @@ EOT
664
658
  rows = adjust_n_cols(rows)
665
659
 
666
660
  if id
667
- buf = %Q[<div id="#{normalize_id(id)}" class="table">\n]
661
+ puts %Q[<div id="#{normalize_id(id)}" class="table">]
668
662
  else
669
- buf = %Q[<div class="table">\n]
663
+ puts %Q[<div class="table">]
670
664
  end
671
665
  begin
672
- buf << table_header(id, caption) unless caption.nil?
666
+ table_header id, caption unless caption.nil?
673
667
  rescue KeyError
674
668
  error "no such table: #{id}"
675
669
  end
676
- buf << table_begin(rows.first.size)
670
+ table_begin rows.first.size
677
671
  return if rows.empty?
678
672
  if sepidx
679
673
  sepidx.times do
680
- buf << tr(rows.shift.map {|s| th(s) })
674
+ tr rows.shift.map {|s| th(s) }
681
675
  end
682
676
  rows.each do |cols|
683
- buf << tr(cols.map {|s| td(s) })
677
+ tr cols.map {|s| td(s) }
684
678
  end
685
679
  else
686
680
  rows.each do |cols|
687
681
  h, *cs = *cols
688
- buf << tr([th(h)] + cs.map {|s| td(s) })
682
+ tr [th(h)] + cs.map {|s| td(s) }
689
683
  end
690
684
  end
691
- buf << table_end
692
- buf << %Q[</div>\n]
693
- buf
685
+ table_end
686
+ puts %Q[</div>]
694
687
  end
695
688
 
696
689
  def table_header(id, caption)
697
690
  if get_chap.nil?
698
- %Q[<p class="caption">#{I18n.t("table")}#{I18n.t("format_number_header_without_chapter", [@chapter.table(id).number])}#{I18n.t("caption_prefix")}#{caption}</p>\n]
691
+ puts %Q[<p class="caption">#{I18n.t("table")}#{I18n.t("format_number_header_without_chapter", [@chapter.table(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}</p>]
699
692
  else
700
- %Q[<p class="caption">#{I18n.t("table")}#{I18n.t("format_number_header", [get_chap, @chapter.table(id).number])}#{I18n.t("caption_prefix")}#{caption}</p>\n]
693
+ puts %Q[<p class="caption">#{I18n.t("table")}#{I18n.t("format_number_header", [get_chap, @chapter.table(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}</p>]
701
694
  end
702
695
  end
703
696
 
704
697
  def table_begin(ncols)
705
- "<table>\n"
698
+ puts '<table>'
706
699
  end
707
700
 
708
701
  def tr(rows)
709
- "<tr>#{rows.join}</tr>\n"
702
+ puts "<tr>#{rows.join}</tr>"
710
703
  end
711
704
 
712
705
  def th(str)
@@ -718,73 +711,95 @@ EOT
718
711
  end
719
712
 
720
713
  def table_end
721
- "</table>\n"
714
+ puts '</table>'
715
+ end
716
+
717
+ def imgtable(lines, id, caption = nil, metric = nil)
718
+ if !@chapter.image(id).bound?
719
+ warn "image not bound: #{id}"
720
+ image_dummy id, caption, lines
721
+ return
722
+ end
723
+
724
+ puts %Q[<div id="#{normalize_id(id)}" class="imgtable image">]
725
+ begin
726
+ table_header id, caption unless caption.nil?
727
+ rescue KeyError
728
+ error "no such table: #{id}"
729
+ end
730
+
731
+ imgtable_image(id, caption, metric)
732
+
733
+ puts %Q[</div>]
734
+ end
735
+
736
+ def imgtable_image(id, caption, metric)
737
+ metrics = parse_metric("html", metric)
738
+ puts %Q[<img src="#{@chapter.image(id).path.sub(/\A\.\//, "")}" alt="#{escape_html(compile_inline(caption))}"#{metrics} />]
722
739
  end
723
740
 
724
741
  def comment(lines, comment = nil)
725
742
  lines ||= []
726
743
  lines.unshift comment unless comment.blank?
727
744
  if @book.config["draft"]
728
- str = lines.map{|line| escape_html(line) }.join("<br />")
729
- return %Q(<div class="draft-comment">#{str}</div>\n)
745
+ str = lines.join("<br />")
746
+ puts %Q(<div class="draft-comment">#{str}</div>)
730
747
  else
731
748
  str = lines.join("\n")
732
- return %Q(<!-- #{escape_comment(str)} -->\n)
749
+ puts %Q(<!-- #{escape_comment(str)} -->)
733
750
  end
734
751
  end
735
752
 
736
753
  def footnote(id, str)
737
754
  if @book.config["epubversion"].to_i == 3
738
- %Q(<div class="footnote" epub:type="footnote" id="fn-#{normalize_id(id)}"><p class="footnote">[*#{@chapter.footnote(id).number}] #{str}</p></div>\n)
755
+ puts %Q(<div class="footnote" epub:type="footnote" id="fn-#{normalize_id(id)}"><p class="footnote">[*#{@chapter.footnote(id).number}] #{compile_inline(str)}</p></div>)
739
756
  else
740
- %Q(<div class="footnote" id="fn-#{normalize_id(id)}"><p class="footnote">[<a href="#fnb-#{normalize_id(id)}">*#{@chapter.footnote(id).number}</a>] #{str}</p></div>\n)
757
+ puts %Q(<div class="footnote" id="fn-#{normalize_id(id)}"><p class="footnote">[<a href="#fnb-#{normalize_id(id)}">*#{@chapter.footnote(id).number}</a>] #{compile_inline(str)}</p></div>)
741
758
  end
742
759
  end
743
760
 
744
761
  def indepimage(id, caption="", metric=nil)
745
762
  metrics = parse_metric("html", metric)
746
763
  caption = "" if caption.nil?
747
- buf = %Q[<div class="image">\n]
764
+ puts %Q[<div class="image">]
748
765
  begin
749
- buf << %Q[<img src="#{@chapter.image(id).path.sub(/\A\.\//, "")}" alt="#{escape_html(caption)}"#{metrics} />\n]
766
+ puts %Q[<img src="#{@chapter.image(id).path.sub(/\A\.\//, "")}" alt="#{escape_html(compile_inline(caption))}"#{metrics} />]
750
767
  rescue
751
- buf << %Q[<pre>missing image: #{id}</pre>\n]
768
+ puts %Q[<pre>missing image: #{id}</pre>]
752
769
  end
753
770
 
754
771
  unless caption.empty?
755
- buf << %Q[<p class="caption">\n]
756
- buf << %Q[#{I18n.t("numberless_image")}#{I18n.t("caption_prefix")}#{caption}\n]
757
- buf << %Q[</p>\n]
772
+ puts %Q[<p class="caption">]
773
+ puts %Q[#{I18n.t("numberless_image")}#{I18n.t("caption_prefix")}#{compile_inline(caption)}]
774
+ puts %Q[</p>]
758
775
  end
759
- buf << %Q[</div>\n]
760
- buf
776
+ puts %Q[</div>]
761
777
  end
762
778
 
763
779
  alias_method :numberlessimage, :indepimage
764
780
 
765
781
  def hr
766
- "<hr />\n"
782
+ puts "<hr />"
767
783
  end
768
784
 
769
785
  def label(id)
770
- %Q(<a id="#{normalize_id(id)}"></a>\n)
786
+ puts %Q(<a id="#{normalize_id(id)}"></a>)
771
787
  end
772
788
 
773
789
  def linebreak
774
- "<br />\n"
790
+ puts "<br />"
775
791
  end
776
792
 
777
793
  def pagebreak
778
- %Q(<br class="pagebreak" />\n)
794
+ puts %Q(<br class="pagebreak" />)
779
795
  end
780
796
 
781
797
  def bpo(lines)
782
- buf = "<bpo>\n"
798
+ puts "<bpo>"
783
799
  lines.each do |line|
784
- buf << detab(line) + "\n"
800
+ puts detab(line)
785
801
  end
786
- buf << "</bpo>\n"
787
- buf
802
+ puts "</bpo>"
788
803
  end
789
804
 
790
805
  def noindent
@@ -792,7 +807,7 @@ EOT
792
807
  end
793
808
 
794
809
  def inline_labelref(idref)
795
- %Q[<a target='#{(idref)}'>「#{I18n.t("label_marker")}#{(idref)}」</a>]
810
+ %Q[<a target='#{escape_html(idref)}'>「#{I18n.t("label_marker")}#{escape_html(idref)}」</a>]
796
811
  end
797
812
 
798
813
  alias_method :inline_ref, :inline_labelref
@@ -841,10 +856,10 @@ EOT
841
856
  end
842
857
 
843
858
  def compile_ruby(base, ruby)
844
- if @book.config["htmlversion"].to_i == 5
845
- %Q[<ruby>#{(base)}<rp>#{I18n.t("ruby_prefix")}</rp><rt>#{(ruby)}</rt><rp>#{I18n.t("ruby_postfix")}</rp></ruby>]
859
+ if @book.htmlversion == 5
860
+ %Q[<ruby>#{escape_html(base)}<rp>#{I18n.t("ruby_prefix")}</rp><rt>#{escape_html(ruby)}</rt><rp>#{I18n.t("ruby_postfix")}</rp></ruby>]
846
861
  else
847
- %Q[<ruby><rb>#{(base)}</rb><rp>#{I18n.t("ruby_prefix")}</rp><rt>#{ruby}</rt><rp>#{I18n.t("ruby_postfix")}</rp></ruby>]
862
+ %Q[<ruby><rb>#{escape_html(base)}</rb><rp>#{I18n.t("ruby_prefix")}</rp><rt>#{ruby}</rt><rp>#{I18n.t("ruby_postfix")}</rp></ruby>]
848
863
  end
849
864
  end
850
865
 
@@ -858,34 +873,34 @@ EOT
858
873
  end
859
874
 
860
875
  def inline_i(str)
861
- %Q(<i>#{str}</i>)
876
+ %Q(<i>#{escape_html(str)}</i>)
862
877
  end
863
878
 
864
879
  def inline_b(str)
865
- %Q(<b>#{str}</b>)
880
+ %Q(<b>#{escape_html(str)}</b>)
866
881
  end
867
882
 
868
883
  def inline_ami(str)
869
- %Q(<span class="ami">#{(str)}</span>)
884
+ %Q(<span class="ami">#{escape_html(str)}</span>)
870
885
  end
871
886
 
872
887
  def inline_bou(str)
873
- %Q(<span class="bou">#{(str)}</span>)
888
+ %Q(<span class="bou">#{escape_html(str)}</span>)
874
889
  end
875
890
 
876
891
  def inline_tti(str)
877
- if @book.config["htmlversion"].to_i == 5
878
- %Q(<code class="tt"><i>#{(str)}</i></code>)
892
+ if @book.htmlversion == 5
893
+ %Q(<code class="tt"><i>#{escape_html(str)}</i></code>)
879
894
  else
880
- %Q(<tt><i>#{(str)}</i></tt>)
895
+ %Q(<tt><i>#{escape_html(str)}</i></tt>)
881
896
  end
882
897
  end
883
898
 
884
899
  def inline_ttb(str)
885
- if @book.config["htmlversion"].to_i == 5
886
- %Q(<code class="tt"><b>#{(str)}</b></code>)
900
+ if @book.htmlversion == 5
901
+ %Q(<code class="tt"><b>#{escape_html(str)}</b></code>)
887
902
  else
888
- %Q(<tt><b>#{(str)}</b></tt>)
903
+ %Q(<tt><b>#{escape_html(str)}</b></tt>)
889
904
  end
890
905
  end
891
906
 
@@ -894,15 +909,15 @@ EOT
894
909
  end
895
910
 
896
911
  def inline_code(str)
897
- if @book.config["htmlversion"].to_i == 5
898
- %Q(<code class="inline-code tt">#{(str)}</code>)
912
+ if @book.htmlversion == 5
913
+ %Q(<code class="inline-code tt">#{escape_html(str)}</code>)
899
914
  else
900
- %Q(<tt class="inline-code">#{(str)}</tt>)
915
+ %Q(<tt class="inline-code">#{escape_html(str)}</tt>)
901
916
  end
902
917
  end
903
918
 
904
919
  def inline_idx(str)
905
- %Q(#{(str)}<!-- IDX:#{escape_comment(escape_html(str))} -->)
920
+ %Q(#{escape_html(str)}<!-- IDX:#{escape_comment(escape_html(str))} -->)
906
921
  end
907
922
 
908
923
  def inline_hidx(str)
@@ -921,7 +936,7 @@ EOT
921
936
  :symbol => MathML::Symbol::CharacterReference)
922
937
  %Q[<span class="equation">#{parser.parse(str, nil)}</span>]
923
938
  else
924
- %Q[<span class="equation">#{(str)}</span>]
939
+ %Q[<span class="equation">#{escape_html(str)}</span>]
925
940
  end
926
941
  end
927
942
 
@@ -930,36 +945,35 @@ EOT
930
945
  end
931
946
 
932
947
  def bibpaper(lines, id, caption)
933
- buf = %Q[<div class="bibpaper">\n]
934
- buf << bibpaper_header(id, caption)
948
+ puts %Q[<div class="bibpaper">]
949
+ bibpaper_header id, caption
935
950
  unless lines.empty?
936
- buf << bibpaper_bibpaper(id, caption, lines)
951
+ bibpaper_bibpaper id, caption, lines
937
952
  end
938
- buf << "</div>" << "\n"
939
- buf
953
+ puts "</div>"
940
954
  end
941
955
 
942
956
  def bibpaper_header(id, caption)
943
- buf = %Q(<a id="bib-#{normalize_id(id)}">)
944
- buf << "[#{@chapter.bibpaper(id).number}]"
945
- buf << %Q(</a>)
946
- buf << " #{(caption)}" << "\n"
957
+ print %Q(<a id="bib-#{normalize_id(id)}">)
958
+ print "[#{@chapter.bibpaper(id).number}]"
959
+ print %Q(</a>)
960
+ puts " #{compile_inline(caption)}"
947
961
  end
948
962
 
949
963
  def bibpaper_bibpaper(id, caption, lines)
950
- lines.join("")
964
+ print split_paragraph(lines).join("")
951
965
  end
952
966
 
953
967
  def inline_bib(id)
954
- %Q(<a href="#{@book.bib_file.gsub(/re\Z/, "html")}#bib-#{normalize_id(id)}">[#{@chapter.bibpaper(id).number}]</a>)
968
+ %Q(<a href="#{@book.bib_file.gsub(/\.re\Z/, ".#{@book.config['htmlext']}")}#bib-#{normalize_id(id)}">[#{@chapter.bibpaper(id).number}]</a>)
955
969
  end
956
970
 
957
971
  def inline_hd_chap(chap, id)
958
972
  n = chap.headline_index.number(id)
959
973
  if chap.number and @book.config["secnolevel"] >= n.split('.').size
960
- str = I18n.t("chapter_quote", "#{n} #{chap.headline(id).caption}")
974
+ str = I18n.t("chapter_quote", "#{n} #{compile_inline(chap.headline(id).caption)}")
961
975
  else
962
- str = I18n.t("chapter_quote", chap.headline(id).caption)
976
+ str = I18n.t("chapter_quote", compile_inline(chap.headline(id).caption))
963
977
  end
964
978
  if @book.config["chapterlink"]
965
979
  anchor = "h"+n.gsub(/\./, "-")
@@ -975,15 +989,12 @@ EOT
975
989
  end
976
990
  private :column_label
977
991
 
978
- def inline_column(id)
992
+ def inline_column_chap(chapter, id)
979
993
  if @book.config["chapterlink"]
980
- %Q(<a href="\##{column_label(id)}" class="columnref">#{I18n.t("column", (@chapter.column(id).caption))}</a>)
994
+ %Q(<a href="\##{column_label(id)}" class="columnref">#{I18n.t("column", escape_html(chapter.column(id).caption))}</a>)
981
995
  else
982
- I18n.t("column", (@chapter.column(id).caption))
996
+ I18n.t("column", escape_html(chapter.column(id).caption))
983
997
  end
984
- rescue KeyError
985
- error "unknown column: #{id}"
986
- nofunc_text("[UnknownColumn:#{id}]")
987
998
  end
988
999
 
989
1000
  def inline_list(id)
@@ -1035,7 +1046,7 @@ EOT
1035
1046
  end
1036
1047
 
1037
1048
  def inline_asis(str, tag)
1038
- %Q(<#{tag}>#{(str)}</#{tag}>)
1049
+ %Q(<#{tag}>#{escape_html(str)}</#{tag}>)
1039
1050
  end
1040
1051
 
1041
1052
  def inline_abbr(str)
@@ -1091,10 +1102,10 @@ EOT
1091
1102
  end
1092
1103
 
1093
1104
  def inline_tt(str)
1094
- if @book.config["htmlversion"].to_i == 5
1095
- %Q(<code class="tt">#{(str)}</code>)
1105
+ if @book.htmlversion == 5
1106
+ %Q(<code class="tt">#{escape_html(str)}</code>)
1096
1107
  else
1097
- %Q(<tt>#{(str)}</tt>)
1108
+ %Q(<tt>#{escape_html(str)}</tt>)
1098
1109
  end
1099
1110
  end
1100
1111
 
@@ -1107,11 +1118,11 @@ EOT
1107
1118
  end
1108
1119
 
1109
1120
  def inline_u(str)
1110
- %Q(<u>#{(str)}</u>)
1121
+ %Q(<u>#{escape_html(str)}</u>)
1111
1122
  end
1112
1123
 
1113
1124
  def inline_recipe(str)
1114
- %Q(<span class="recipe">「#{(str)}」</span>)
1125
+ %Q(<span class="recipe">「#{escape_html(str)}」</span>)
1115
1126
  end
1116
1127
 
1117
1128
  def inline_icon(id)
@@ -1128,12 +1139,19 @@ EOT
1128
1139
 
1129
1140
  def inline_comment(str)
1130
1141
  if @book.config["draft"]
1131
- %Q(<span class="draft-comment">#{(str)}</span>)
1142
+ %Q(<span class="draft-comment">#{escape_html(str)}</span>)
1132
1143
  else
1133
1144
  %Q(<!-- #{escape_comment(escape_html(str))} -->)
1134
1145
  end
1135
1146
  end
1136
1147
 
1148
+ def inline_tcy(str)
1149
+ # 縦中横用のtcy、uprightのCSSスタイルについては電書協ガイドラインを参照
1150
+ style = "tcy"
1151
+ style = "upright" if str.size == 1 && str.match(/[[:ascii:]]/)
1152
+ %Q[<span class="#{style}">#{escape_html(str)}</span>]
1153
+ end
1154
+
1137
1155
  def inline_raw(str)
1138
1156
  super(str)
1139
1157
  end
@@ -1143,21 +1161,19 @@ EOT
1143
1161
  end
1144
1162
 
1145
1163
  def compile_href(url, label)
1146
- %Q(<a href="#{escape_html(url)}" class="link">#{label.nil? ? (url) : (label)}</a>)
1164
+ if @book.config["externallink"]
1165
+ %Q(<a href="#{escape_html(url)}" class="link">#{label.nil? ? escape_html(url) : escape_html(label)}</a>)
1166
+ else
1167
+ label.nil? ? escape_html(url) : I18n.t('external_link', [escape_html(label), escape_html(url)])
1168
+ end
1147
1169
  end
1148
1170
 
1149
1171
  def flushright(lines)
1150
- result = ""
1151
- if @book.config["deprecated-blocklines"].nil?
1152
- result << lines.join("").gsub("<p>", "<p class=\"flushright\">")
1153
- else
1154
- error "deprecated-blocklines is obsoleted."
1155
- end
1156
- result
1172
+ puts split_paragraph(lines).join("\n").gsub("<p>", "<p class=\"flushright\">")
1157
1173
  end
1158
1174
 
1159
1175
  def centering(lines)
1160
- lines.join("").gsub("<p>", "<p class=\"center\">")
1176
+ puts split_paragraph(lines).join("\n").gsub("<p>", "<p class=\"center\">")
1161
1177
  end
1162
1178
 
1163
1179
  def image_ext
@@ -1169,4 +1185,4 @@ EOT
1169
1185
  end
1170
1186
  end
1171
1187
 
1172
- end # module ReVIEW
1188
+ end # module ReVIEW