review 3.0.0 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-win.yml +39 -0
  3. data/.github/workflows/ruby.yml +27 -0
  4. data/.rubocop.yml +50 -12
  5. data/.travis.yml +17 -8
  6. data/Dockerfile +21 -5
  7. data/NEWS.ja.md +358 -0
  8. data/NEWS.md +358 -1
  9. data/README.md +11 -8
  10. data/appveyor.yml +1 -3
  11. data/bin/review-catalog-converter +4 -4
  12. data/bin/review-check +8 -8
  13. data/bin/review-checkdep +1 -1
  14. data/bin/review-compile +12 -12
  15. data/bin/review-epubmaker +3 -35
  16. data/bin/review-idgxmlmaker +16 -0
  17. data/bin/review-index +2 -89
  18. data/bin/review-preproc +14 -19
  19. data/bin/review-validate +3 -3
  20. data/bin/review-vol +4 -78
  21. data/doc/LICENSE +1 -1
  22. data/doc/config.yml.sample +46 -12
  23. data/doc/config.yml.sample-simple +4 -2
  24. data/doc/format.ja.md +37 -13
  25. data/doc/format.md +35 -20
  26. data/doc/pdfmaker.ja.md +43 -1
  27. data/doc/pdfmaker.md +42 -1
  28. data/doc/quickstart.ja.md +46 -26
  29. data/doc/quickstart.md +38 -17
  30. data/lib/epubmaker/epubcommon.rb +10 -5
  31. data/lib/epubmaker/epubv2.rb +1 -1
  32. data/lib/epubmaker/epubv3.rb +1 -0
  33. data/lib/epubmaker/producer.rb +4 -2
  34. data/lib/review/book.rb +1 -1
  35. data/lib/review/book/base.rb +38 -79
  36. data/lib/review/book/chapter.rb +18 -3
  37. data/lib/review/book/compilable.rb +6 -5
  38. data/lib/review/book/index.rb +69 -101
  39. data/lib/review/book/index/item.rb +40 -0
  40. data/lib/review/book/page_metric.rb +7 -7
  41. data/lib/review/book/part.rb +28 -5
  42. data/lib/review/book/volume.rb +3 -4
  43. data/lib/review/builder.rb +105 -44
  44. data/lib/review/catalog.rb +13 -16
  45. data/lib/review/compiler.rb +84 -72
  46. data/lib/review/configure.rb +19 -8
  47. data/lib/review/epub2html.rb +37 -4
  48. data/lib/review/epubmaker.rb +62 -7
  49. data/lib/review/extentions/string.rb +0 -4
  50. data/lib/review/htmlbuilder.rb +102 -115
  51. data/lib/review/htmlutils.rb +2 -3
  52. data/lib/review/i18n.rb +2 -2
  53. data/lib/review/i18n.yml +9 -0
  54. data/lib/review/idgxmlbuilder.rb +153 -74
  55. data/lib/review/idgxmlmaker.rb +191 -0
  56. data/lib/review/init-web/finish.html +10 -0
  57. data/lib/review/init-web/index.html +190 -0
  58. data/lib/review/init-web/review-layout-design.js +691 -0
  59. data/lib/review/init.rb +125 -34
  60. data/lib/review/latexbuilder.rb +199 -88
  61. data/lib/review/lineinput.rb +1 -1
  62. data/lib/review/location.rb +32 -0
  63. data/lib/review/logger.rb +4 -8
  64. data/lib/review/makerhelper.rb +24 -5
  65. data/lib/review/markdownbuilder.rb +31 -37
  66. data/lib/review/md2inaobuilder.rb +3 -5
  67. data/lib/review/pdfmaker.rb +44 -22
  68. data/lib/review/plaintextbuilder.rb +106 -85
  69. data/lib/review/preprocessor.rb +32 -41
  70. data/lib/review/rstbuilder.rb +33 -33
  71. data/lib/review/textmaker.rb +19 -3
  72. data/lib/review/textutils.rb +76 -2
  73. data/lib/review/tocprinter.rb +231 -102
  74. data/lib/review/topbuilder.rb +114 -61
  75. data/lib/review/update.rb +19 -19
  76. data/lib/review/version.rb +1 -1
  77. data/lib/review/volumeprinter.rb +99 -0
  78. data/lib/review/webmaker.rb +11 -4
  79. data/lib/review/webtocprinter.rb +38 -35
  80. data/lib/review/yamlloader.rb +26 -16
  81. data/review.gemspec +6 -4
  82. data/samples/sample-book/README.md +7 -2
  83. data/samples/sample-book/src/.gitignore +154 -0
  84. data/samples/sample-book/src/config-ebook.yml +4 -0
  85. data/samples/sample-book/src/config-jlreq-ebook.yml +4 -0
  86. data/samples/sample-book/src/config-jlreq.yml +6 -0
  87. data/samples/sample-book/src/config.yml +2 -2
  88. data/samples/sample-book/src/lib/tasks/review.rake +29 -14
  89. data/samples/sample-book/src/lib/tasks/z01_copy_sty.rake +14 -8
  90. data/samples/syntax-book/ch01.re +4 -2
  91. data/samples/syntax-book/ch02.re +8 -16
  92. data/samples/syntax-book/ch03.re +3 -6
  93. data/samples/syntax-book/config-jlreq-lualatex.yml +4 -0
  94. data/samples/syntax-book/config-jlreq.yml +5 -0
  95. data/samples/syntax-book/config-print.yml +3 -0
  96. data/samples/syntax-book/config.yml +1 -1
  97. data/samples/syntax-book/lib/tasks/review.rake +30 -15
  98. data/samples/syntax-book/lib/tasks/z01_copy_sty.rake +14 -8
  99. data/templates/latex/config.erb +16 -0
  100. data/templates/latex/layout.tex.erb +4 -0
  101. data/templates/latex/review-jlreq/review-base.sty +150 -61
  102. data/templates/latex/review-jlreq/review-jlreq.cls +74 -8
  103. data/templates/latex/review-jlreq/review-style.sty +4 -1
  104. data/templates/latex/review-jsbook/README.md +39 -0
  105. data/templates/latex/review-jsbook/review-base.sty +101 -23
  106. data/templates/latex/review-jsbook/review-jsbook.cls +28 -5
  107. data/templates/latex/review-jsbook/review-style.sty +5 -2
  108. data/templates/opf/epubv3.opf.erb +1 -0
  109. data/templates/web/html/layout-html5.html.erb +2 -2
  110. data/test/assets/test_template.tex +24 -3
  111. data/test/assets/test_template_backmatter.tex +24 -3
  112. data/test/test_book.rb +75 -21
  113. data/test/test_book_chapter.rb +4 -2
  114. data/test/test_book_part.rb +3 -3
  115. data/test/test_builder.rb +16 -0
  116. data/test/test_catalog.rb +24 -42
  117. data/test/test_catalog_converter_cmd.rb +1 -1
  118. data/test/test_epubmaker_cmd.rb +14 -7
  119. data/test/test_helper.rb +15 -7
  120. data/test/test_htmlbuilder.rb +909 -159
  121. data/test/test_i18n.rb +25 -25
  122. data/test/test_idgxmlbuilder.rb +395 -38
  123. data/test/test_idgxmlmaker_cmd.rb +46 -0
  124. data/test/test_image_finder.rb +52 -70
  125. data/test/test_index.rb +50 -10
  126. data/test/test_latexbuilder.rb +1194 -106
  127. data/test/test_latexbuilder_v2.rb +628 -97
  128. data/test/test_logger.rb +14 -1
  129. data/test/test_makerhelper.rb +3 -3
  130. data/test/test_markdownbuilder.rb +134 -16
  131. data/test/test_md2inaobuilder.rb +32 -9
  132. data/test/test_pdfmaker.rb +18 -1
  133. data/test/test_pdfmaker_cmd.rb +100 -6
  134. data/test/test_plaintextbuilder.rb +371 -25
  135. data/test/test_preprocessor.rb +2 -16
  136. data/test/test_rstbuilder.rb +249 -26
  137. data/test/test_textmaker_cmd.rb +54 -0
  138. data/test/test_textutils.rb +109 -2
  139. data/test/test_topbuilder.rb +546 -31
  140. data/test/test_update.rb +17 -8
  141. data/test/test_webtocprinter.rb +66 -34
  142. data/test/test_yamlloader.rb +13 -0
  143. data/vendor/jsclasses/LICENSE +1 -1
  144. data/vendor/jsclasses/jis/jsarticle.cls +53 -14
  145. data/vendor/jsclasses/jis/jsbook.cls +53 -14
  146. data/vendor/jsclasses/jis/jsclasses.dtx +84 -25
  147. data/vendor/jsclasses/jis/jslogo.dtx +4 -4
  148. data/vendor/jsclasses/jis/jslogo.sty +3 -3
  149. data/vendor/jsclasses/jis/jspf.cls +52 -13
  150. data/vendor/jsclasses/jis/jsreport.cls +53 -14
  151. data/vendor/jsclasses/jis/kiyou.cls +53 -14
  152. data/vendor/jsclasses/jis/okumacro.dtx +4 -5
  153. data/vendor/jsclasses/jis/okumacro.sty +3 -4
  154. data/vendor/jsclasses/jsarticle.cls +53 -14
  155. data/vendor/jsclasses/jsbook.cls +53 -14
  156. data/vendor/jsclasses/jsclasses.dtx +84 -25
  157. data/vendor/jsclasses/jsclasses.pdf +0 -0
  158. data/vendor/jsclasses/jslogo.dtx +4 -4
  159. data/vendor/jsclasses/jslogo.pdf +0 -0
  160. data/vendor/jsclasses/jslogo.sty +3 -3
  161. data/vendor/jsclasses/jspf.cls +52 -13
  162. data/vendor/jsclasses/jsreport.cls +53 -14
  163. data/vendor/jsclasses/kiyou.cls +53 -14
  164. data/vendor/jsclasses/okumacro.dtx +4 -5
  165. data/vendor/jsclasses/okumacro.pdf +0 -0
  166. data/vendor/jsclasses/okumacro.sty +3 -4
  167. metadata +55 -10
  168. data/lib/review/tocparser.rb +0 -271
  169. data/samples/syntax-book/review-ext.rb +0 -14
  170. data/test/test_tocparser.rb +0 -25
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2018 Masanori Kado, Masayoshi Takahashi, Kenshi Muto
2
+ # Copyright (c) 2018-2019 Masanori Kado, Masayoshi Takahashi, Kenshi Muto
3
3
  #
4
4
  # This program is free software.
5
5
  # You can distribute or modify this program under the terms of
@@ -18,12 +18,12 @@ module ReVIEW
18
18
  new.execute(*args)
19
19
  end
20
20
 
21
- TEX_DOCUMENTCLASS_OPTS = {
22
- 'review-jsbook' => 'media=print,paper=a5',
23
- 'review-jlreq' => 'media=print,paper=a5'
24
- }
25
-
26
21
  def initialize
22
+ @tex_documentclass_opts = {
23
+ 'review-jsbook' => 'media=print,paper=a5',
24
+ 'review-jlreq' => 'media=print,paper=a5'
25
+ }
26
+
27
27
  @template = 'review-jsbook'
28
28
  @logger = ReVIEW.logger
29
29
  @review_dir = File.dirname(File.expand_path('..', __dir__))
@@ -32,15 +32,25 @@ module ReVIEW
32
32
  def execute(*args)
33
33
  initdir = parse_options(args)
34
34
 
35
+ if @webui
36
+ start_webui
37
+ unless @web_result
38
+ @logger.error 'Aborted.'
39
+ exit 1
40
+ end
41
+ @template = @web_result[0]
42
+ @tex_documentclass_opts[@template] = @web_result[1]
43
+ end
44
+
35
45
  generate_dir(initdir) do |dir|
36
46
  generate_catalog_file(dir)
37
47
  generate_sample(dir)
38
48
  generate_images_dir(dir)
39
49
  generate_cover_image(dir)
40
- generate_layout(dir)
41
50
  generate_style(dir)
42
51
  generate_texmacro(dir)
43
52
  generate_config(dir)
53
+ generate_gitignore(dir)
44
54
  generate_locale(dir) if @locale
45
55
  generate_rakefile(dir)
46
56
  generate_gemfile(dir)
@@ -50,6 +60,9 @@ module ReVIEW
50
60
  end
51
61
 
52
62
  def parse_options(args)
63
+ @port = 18000
64
+ @bind = '0'
65
+
53
66
  opts = OptionParser.new
54
67
  opts.version = ReVIEW::VERSION
55
68
  opts.banner = "Usage: #{File.basename($PROGRAM_NAME)} [option] dirname"
@@ -63,23 +76,35 @@ module ReVIEW
63
76
  opts.on('-l', '--locale', 'generate locale.yml file.') do
64
77
  @locale = true
65
78
  end
66
- opts.on('--latex-template name', 'specify LaTeX template name. (default: review-jsbook)') do |tname|
79
+ opts.on('-t', '--latex-template name', 'specify LaTeX template name. (default: review-jsbook)') do |tname|
67
80
  @template = tname
68
81
  end
69
82
  opts.on('', '--epub-version VERSION', 'define EPUB version.') do |version|
70
83
  @epub_version = version
71
84
  end
85
+ opts.on('', '--without-config-comment', "don't include comments in config.yml.") do
86
+ @without_config_comment = true
87
+ end
72
88
  opts.on('', '--without-doc', "don't generate doc files.") do
73
89
  @without_doc = true
74
90
  end
75
91
  opts.on('-p', '--package archivefile', 'extract from local or network archive.') do |archive|
76
92
  @archive = archive
77
93
  end
94
+ opts.on('-w', '--wizard', 'launch Web based layout configuration.') do
95
+ @webui = true
96
+ end
97
+ opts.on('', '--port port', 'port to use for Web based layout configuration. (default: 18000)') do |port|
98
+ @port = port
99
+ end
100
+ opts.on('', '--bind bindaddress', 'address to use for Web based layout configuration. (default: 0 (any))') do |bind|
101
+ @bind = bind
102
+ end
78
103
 
79
104
  begin
80
105
  opts.parse!(args)
81
- rescue OptionParser::ParseError => err
82
- @logger.error err.message
106
+ rescue OptionParser::ParseError => e
107
+ @logger.error e.message
83
108
  $stderr.puts opts.help
84
109
  exit 1
85
110
  end
@@ -99,7 +124,7 @@ module ReVIEW
99
124
  @logger.error "#{dir} already exists."
100
125
  exit 1
101
126
  end
102
- FileUtils.mkdir_p dir
127
+ FileUtils.mkdir_p(dir)
103
128
  yield dir
104
129
  end
105
130
 
@@ -109,10 +134,6 @@ module ReVIEW
109
134
  end
110
135
  end
111
136
 
112
- def generate_layout(dir)
113
- FileUtils.mkdir_p File.join(dir, 'layouts')
114
- end
115
-
116
137
  def generate_catalog_file(dir)
117
138
  File.open(File.join(dir, 'catalog.yml'), 'w') do |file|
118
139
  file.write <<-EOS
@@ -154,31 +175,53 @@ EOS
154
175
  content.gsub!(/^#.*htmlversion:.*$/, 'htmlversion: 4')
155
176
  end
156
177
 
157
- if TEX_DOCUMENTCLASS_OPTS[@template]
158
- content.gsub!(/^#\s*texdocumentclass:.*$/, %Q(texdocumentclass: ["#{@template}", "#{TEX_DOCUMENTCLASS_OPTS[@template]}"]))
178
+ if @tex_documentclass_opts[@template]
179
+ content.gsub!(/^#\s*texdocumentclass:.*$/, %Q(texdocumentclass: ["#{@template}", "#{@tex_documentclass_opts[@template]}"]))
180
+ end
181
+
182
+ if @without_config_comment
183
+ content = content.split("\n").delete_if { |l| l.strip.start_with?('#') || l.strip.empty? }.join("\n")
184
+ end
185
+
186
+ File.open(File.join(dir, 'config.yml'), 'w') { |f| f.write content }
187
+ if @webui && !@web_result[2].empty?
188
+ File.open(File.join(dir, 'config-ebook.yml'), 'w') do |f|
189
+ f.puts <<EOT
190
+ # for ebook PDF
191
+ # REVIEW_CONFIG_FILE=config.yml rake pdf
192
+ inherit: ["config.yml"]
193
+ # bookname: book-ebook
194
+ texdocumentclass: ["#{@web_result[0]}", "#{@web_result[2]}"]
195
+ EOT
196
+ end
159
197
  end
198
+ end
160
199
 
161
- File.open(File.join(dir, 'config.yml'), 'w') { |f| f.write(content) }
200
+ def generate_gitignore(dir)
201
+ FileUtils.cp(File.join(@review_dir, 'samples/sample-book/src/.gitignore'), dir)
162
202
  end
163
203
 
164
204
  def generate_style(dir)
165
- FileUtils.cp File.join(@review_dir, 'samples/sample-book/src/style.css'), dir
205
+ FileUtils.cp(File.join(@review_dir, 'samples/sample-book/src/style.css'), dir)
166
206
  end
167
207
 
168
208
  def generate_texmacro(dir)
169
209
  texmacrodir = File.join(dir, 'sty')
170
- FileUtils.mkdir_p texmacrodir
210
+ FileUtils.mkdir_p(texmacrodir)
171
211
  tdir = File.join(@review_dir, 'templates/latex', @template)
172
212
  @logger.error "#{tdir} not found." unless File.exist?(tdir)
173
- FileUtils.cp Dir.glob(File.join(tdir, '*.*')), texmacrodir
174
- # provide jsbook from vendor/. current version is 2018/06/23
175
- FileUtils.cp File.join(@review_dir, 'vendor/jsclasses/jsbook.cls'), File.join(texmacrodir, 'jsbook.cls')
176
- # provide gentombow from vendor/. current version is 2018/08/30 v0.9j
177
- FileUtils.cp File.join(@review_dir, 'vendor/gentombow/gentombow.sty'), File.join(texmacrodir, 'gentombow.sty')
213
+ FileUtils.cp(Dir.glob(File.join(tdir, '*.*')), texmacrodir)
214
+
215
+ if @template == 'review-jsbook'
216
+ # provide jsbook from vendor/. current version is 2018/06/23
217
+ FileUtils.cp(File.join(@review_dir, 'vendor/jsclasses/jsbook.cls'), File.join(texmacrodir, 'jsbook.cls'))
218
+ # provide gentombow from vendor/. current version is 2018/08/30 v0.9j
219
+ FileUtils.cp(File.join(@review_dir, 'vendor/gentombow/gentombow.sty'), File.join(texmacrodir, 'gentombow.sty'))
220
+ end
178
221
  end
179
222
 
180
223
  def generate_rakefile(dir)
181
- FileUtils.mkdir_p File.join(dir, 'lib/tasks')
224
+ FileUtils.mkdir_p(File.join(dir, 'lib/tasks'))
182
225
 
183
226
  File.open(File.join(dir, 'Rakefile'), 'w') do |file|
184
227
  file.write <<-EOS
@@ -193,7 +236,7 @@ EOS
193
236
  end
194
237
 
195
238
  def generate_locale(dir)
196
- FileUtils.cp File.join(@review_dir, 'lib/review/i18n.yml'), File.join(dir, 'locale.yml')
239
+ FileUtils.cp(File.join(@review_dir, 'lib/review/i18n.yml'), File.join(dir, 'locale.yml'))
197
240
  end
198
241
 
199
242
  def generate_gemfile(dir)
@@ -209,9 +252,9 @@ EOS
209
252
 
210
253
  def generate_doc(dir)
211
254
  docdir = File.join(dir, 'doc')
212
- FileUtils.mkdir_p docdir
255
+ FileUtils.mkdir_p(docdir)
213
256
  md_files = Dir.glob(File.join(@review_dir, 'doc/*.md')).map.to_a
214
- FileUtils.cp md_files, docdir
257
+ FileUtils.cp(md_files, docdir)
215
258
  end
216
259
 
217
260
  def download_and_extract_archive(dir, filename)
@@ -226,8 +269,8 @@ EOS
226
269
  begin
227
270
  @logger.info "Downloading from #{filename}"
228
271
  zipdata = Net::HTTP.get(URI.parse(filename))
229
- rescue StandardError => err
230
- @logger.error "Failed to download #{filename}: #{err.message}"
272
+ rescue StandardError => e
273
+ @logger.error "Failed to download #{filename}: #{e.message}"
231
274
  exit 1
232
275
  end
233
276
 
@@ -256,7 +299,7 @@ EOS
256
299
  next
257
300
  end
258
301
 
259
- if fname =~ %r{\A/} || fname =~ /\.\./ # simple fool proof
302
+ if fname.start_with?('/') || fname =~ /\.\./ # simple fool proof
260
303
  made = nil
261
304
  break
262
305
  end
@@ -267,8 +310,56 @@ EOS
267
310
  made = true
268
311
  end
269
312
  raise Zip::Error unless made
270
- rescue Zip::Error => err
271
- @logger.error "#{originalfilename} seems invalid or broken zip file: #{err.message}"
313
+ rescue Zip::Error => e
314
+ @logger.error "#{originalfilename} seems invalid or broken zip file: #{e.message}"
315
+ end
316
+ end
317
+
318
+ def start_webui
319
+ require 'webrick'
320
+ web_config = {
321
+ BindAddress: @bind,
322
+ Port: @port,
323
+ HTTPVersion: WEBrick::HTTPVersion.new('1.1'),
324
+ AccessLog: [[File.open(IO::NULL, 'w'), '']]
325
+ }
326
+
327
+ bind_address = (@bind == '0') ? '<thishost>' : @bind
328
+ puts "Please access http://#{bind_address}:#{web_config[:Port]} from Web browser."
329
+ begin
330
+ @web_server = WEBrick::HTTPServer.new(web_config)
331
+ rescue StandardError => e
332
+ @logger.error "Error: #{e}"
333
+ exit 1
334
+ end
335
+
336
+ @web_result = nil
337
+ web_mounts
338
+
339
+ trap(:INT) { @web_server.shutdown }
340
+ @web_server.start
341
+
342
+ # validation
343
+ if @web_result
344
+ @web_result.each do |s|
345
+ if s !~ /\A[a-z0-9=_,\.-]*\Z/i
346
+ @web_result = nil
347
+ break
348
+ end
349
+ end
350
+ end
351
+ end
352
+
353
+ def web_mounts
354
+ htmldir = File.join(@review_dir, 'lib', 'review', 'init-web')
355
+ @web_server.mount('/', WEBrick::HTTPServlet::FileHandler, File.join(htmldir, 'index.html'))
356
+ @web_server.mount('/review-layout-design.js', WEBrick::HTTPServlet::FileHandler, File.join(htmldir, 'review-layout-design.js'))
357
+
358
+ @web_server.mount_proc('/finish') do |req, res|
359
+ @web_result = [req.query['cls'], req.query['result_print'], req.query['result_ebook']]
360
+ res.content_type = 'text/html'
361
+ res.body = File.read(File.join(htmldir, 'finish.html'))
362
+ @web_server.shutdown
272
363
  end
273
364
  end
274
365
  end
@@ -1,6 +1,6 @@
1
1
  # Copyright (c) 2002-2007 Minero Aoki
2
2
  # 2008-2009 Minero Aoki, Kenshi Muto
3
- # 2010-2018 Minero Aoki, Kenshi Muto, TAKAHASHI Masayoshi
3
+ # 2010-2020 Minero Aoki, Kenshi Muto, TAKAHASHI Masayoshi
4
4
  #
5
5
  # This program is free software.
6
6
  # You can distribute or modify this program under the terms of
@@ -32,7 +32,6 @@ module ReVIEW
32
32
  @blank_needed = false
33
33
  @latex_tsize = nil
34
34
  @tsize = nil
35
- @table_caption = nil
36
35
  @cellwidth = nil
37
36
  @ol_num = nil
38
37
  @first_line_num = nil
@@ -61,7 +60,7 @@ module ReVIEW
61
60
  require 'nkf'
62
61
  @index_mecab = MeCab::Tagger.new(@book.config['pdfmaker']['makeindex_mecab_opts'])
63
62
  rescue LoadError
64
- error 'not found MeCab'
63
+ warn 'not found MeCab'
65
64
  end
66
65
  end
67
66
 
@@ -257,7 +256,11 @@ module ReVIEW
257
256
  end
258
257
 
259
258
  def ul_item(lines)
260
- str = lines.join
259
+ str = join_lines_to_paragraph(lines)
260
+ unless @book.config['join_lines_by_lang']
261
+ str = lines.map(&:chomp).join("\n")
262
+ end
263
+
261
264
  str.sub!(/\A(\[)/) { '\lbrack{}' }
262
265
  puts '\item ' + str
263
266
  end
@@ -276,7 +279,11 @@ module ReVIEW
276
279
  end
277
280
 
278
281
  def ol_item(lines, _num)
279
- str = lines.join
282
+ str = join_lines_to_paragraph(lines)
283
+ unless @book.config['join_lines_by_lang']
284
+ str = lines.map(&:chomp).join("\n")
285
+ end
286
+
280
287
  str.sub!(/\A(\[)/) { '\lbrack{}' }
281
288
  puts '\item ' + str
282
289
  end
@@ -292,13 +299,16 @@ module ReVIEW
292
299
  end
293
300
 
294
301
  def dt(str)
295
- str.sub!(/\[/) { '\lbrack{}' }
296
- str.sub!(/\]/) { '\rbrack{}' }
302
+ str = str.gsub('[', '\lbrack{}').gsub(']', '\rbrack{}')
297
303
  puts '\item[' + str + '] \mbox{} \\\\'
298
304
  end
299
305
 
300
306
  def dd(lines)
301
- puts lines.join
307
+ if @book.config['join_lines_by_lang']
308
+ puts join_lines_to_paragraph(lines)
309
+ else
310
+ puts lines.map(&:chomp).join("\n")
311
+ end
302
312
  end
303
313
 
304
314
  def dl_end
@@ -308,8 +318,10 @@ module ReVIEW
308
318
 
309
319
  def paragraph(lines)
310
320
  blank
311
- lines.each do |line|
312
- puts line
321
+ if @book.config['join_lines_by_lang']
322
+ puts join_lines_to_paragraph(lines)
323
+ else
324
+ lines.each { |line| puts line }
313
325
  end
314
326
  blank
315
327
  end
@@ -319,22 +331,35 @@ module ReVIEW
319
331
  end
320
332
 
321
333
  def read(lines)
322
- latex_block 'quotation', lines
334
+ latex_block('quotation', lines)
323
335
  end
324
336
 
325
337
  alias_method :lead, :read
326
338
 
339
+ def highlight?
340
+ @book.config['highlight'] &&
341
+ @book.config['highlight']['latex']
342
+ end
343
+
327
344
  def highlight_listings?
328
345
  @book.config['highlight'] && @book.config['highlight']['latex'] == 'listings'
329
346
  end
330
347
  private :highlight_listings?
331
348
 
349
+ def code_line(_type, line, _idx, _id, _caption, _lang)
350
+ detab(line) + "\n"
351
+ end
352
+
353
+ def code_line_num(_type, line, first_line_num, idx, _id, _caption, _lang)
354
+ detab((idx + first_line_num).to_s.rjust(2) + ': ' + line) + "\n"
355
+ end
356
+
332
357
  def emlist(lines, caption = nil, lang = nil)
333
358
  blank
334
359
  if highlight_listings?
335
360
  common_code_block_lst(nil, lines, 'reviewemlistlst', 'title', caption, lang)
336
361
  else
337
- common_code_block(nil, lines, 'reviewemlist', caption, lang) { |line, _idx| detab(line) + "\n" }
362
+ common_code_block(nil, lines, 'reviewemlist', caption, lang) { |line, idx| code_line('emlist', line, idx, nil, caption, lang) }
338
363
  end
339
364
  end
340
365
 
@@ -344,7 +369,7 @@ module ReVIEW
344
369
  if highlight_listings?
345
370
  common_code_block_lst(nil, lines, 'reviewemlistnumlst', 'title', caption, lang, first_line_num: first_line_num)
346
371
  else
347
- common_code_block(nil, lines, 'reviewemlist', caption, lang) { |line, idx| detab((idx + first_line_num).to_s.rjust(2) + ': ' + line) + "\n" }
372
+ common_code_block(nil, lines, 'reviewemlist', caption, lang) { |line, idx| code_line_num('emlistnum', line, first_line_num, idx, nil, caption, lang) }
348
373
  end
349
374
  end
350
375
 
@@ -353,7 +378,7 @@ module ReVIEW
353
378
  if highlight_listings?
354
379
  common_code_block_lst(id, lines, 'reviewlistlst', 'caption', caption, lang)
355
380
  else
356
- common_code_block(id, lines, 'reviewlist', caption, lang) { |line, _idx| detab(line) + "\n" }
381
+ common_code_block(id, lines, 'reviewlist', caption, lang) { |line, idx| code_line('list', line, idx, id, caption, lang) }
357
382
  end
358
383
  end
359
384
 
@@ -363,7 +388,7 @@ module ReVIEW
363
388
  if highlight_listings?
364
389
  common_code_block_lst(id, lines, 'reviewlistnumlst', 'caption', caption, lang, first_line_num: first_line_num)
365
390
  else
366
- common_code_block(id, lines, 'reviewlist', caption, lang) { |line, idx| detab((idx + first_line_num).to_s.rjust(2) + ': ' + line) + "\n" }
391
+ common_code_block(id, lines, 'reviewlist', caption, lang) { |line, idx| code_line_num('listnum', line, first_line_num, idx, id, caption, lang) }
367
392
  end
368
393
  end
369
394
 
@@ -372,24 +397,25 @@ module ReVIEW
372
397
  common_code_block_lst(nil, lines, 'reviewcmdlst', 'title', caption, lang)
373
398
  else
374
399
  blank
375
- common_code_block(nil, lines, 'reviewcmd', caption, lang) { |line, _idx| detab(line) + "\n" }
400
+ common_code_block(nil, lines, 'reviewcmd', caption, lang) { |line, idx| code_line('cmd', line, idx, nil, caption, lang) }
376
401
  end
377
402
  end
378
403
 
379
404
  def common_code_block(id, lines, command, caption, _lang)
380
405
  @doc_status[:caption] = true
406
+ captionstr = nil
381
407
  unless @book.config.check_version('2', exception: false)
382
408
  puts '\\begin{reviewlistblock}'
383
409
  end
384
410
  if caption.present?
385
411
  if command =~ /emlist/ || command =~ /cmd/ || command =~ /source/
386
- puts macro(command + 'caption', compile_inline(caption))
412
+ captionstr = macro(command + 'caption', compile_inline(caption))
387
413
  else
388
414
  begin
389
415
  if get_chap.nil?
390
- puts macro('reviewlistcaption', "#{I18n.t('list')}#{I18n.t('format_number_header_without_chapter', [@chapter.list(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
416
+ captionstr = macro('reviewlistcaption', "#{I18n.t('list')}#{I18n.t('format_number_header_without_chapter', [@chapter.list(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
391
417
  else
392
- puts macro('reviewlistcaption', "#{I18n.t('list')}#{I18n.t('format_number_header', [get_chap, @chapter.list(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
418
+ captionstr = macro('reviewlistcaption', "#{I18n.t('list')}#{I18n.t('format_number_header', [get_chap, @chapter.list(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
393
419
  end
394
420
  rescue KeyError
395
421
  error "no such list: #{id}"
@@ -397,6 +423,11 @@ module ReVIEW
397
423
  end
398
424
  end
399
425
  @doc_status[:caption] = nil
426
+
427
+ if caption_top?('list') && captionstr
428
+ puts captionstr
429
+ end
430
+
400
431
  body = ''
401
432
  lines.each_with_index do |line, idx|
402
433
  body.concat(yield(line, idx))
@@ -404,6 +435,11 @@ module ReVIEW
404
435
  puts macro('begin', command)
405
436
  print body
406
437
  puts macro('end', command)
438
+
439
+ if !caption_top?('list') && captionstr
440
+ puts captionstr
441
+ end
442
+
407
443
  unless @book.config.check_version('2', exception: false)
408
444
  puts '\\end{reviewlistblock}'
409
445
  end
@@ -414,7 +450,7 @@ module ReVIEW
414
450
  if title == 'title' && caption.blank? && @book.config.check_version('2', exception: false)
415
451
  print '\vspace{-1.5em}'
416
452
  end
417
- body = lines.inject('') { |i, j| i + detab(unescape(j)) + "\n" }
453
+ body = lines.inject('') { |i, j| i + detab(j) + "\n" }
418
454
  args = make_code_block_args(title, caption, lang, first_line_num: first_line_num)
419
455
  puts %Q(\\begin{#{command}}[#{args}])
420
456
  print body
@@ -449,15 +485,23 @@ module ReVIEW
449
485
  if highlight_listings?
450
486
  common_code_block_lst(nil, lines, 'reviewsourcelst', 'title', caption, lang)
451
487
  else
452
- common_code_block(nil, lines, 'reviewsource', caption, lang) { |line, _idx| detab(line) + "\n" }
488
+ common_code_block(nil, lines, 'reviewsource', caption, lang) { |line, idx| code_line('source', line, idx, nil, caption, lang) }
453
489
  end
454
490
  end
455
491
 
456
492
  def image_header(id, caption)
457
493
  end
458
494
 
495
+ def parse_metric(type, metric)
496
+ s = super(type, metric)
497
+ if @book.config['pdfmaker']['use_original_image_size'] && s.empty? && !metric.present?
498
+ return ' ' # pass empty to \reviewincludegraphics
499
+ end
500
+ s
501
+ end
502
+
459
503
  def handle_metric(str)
460
- if @book.config['image_scale2width'] && str =~ /\Ascale=([\d.]+)\Z/
504
+ if @book.config['pdfmaker']['image_scale2width'] && str =~ /\Ascale=([\d.]+)\Z/
461
505
  return "width=#{$1}\\maxwidth"
462
506
  end
463
507
  str
@@ -468,18 +512,39 @@ module ReVIEW
468
512
  end
469
513
 
470
514
  def image_image(id, caption, metric)
515
+ captionstr = nil
516
+ @doc_status[:caption] = true
517
+ if @book.config.check_version('2', exception: false)
518
+ captionstr = macro('caption', compile_inline(caption)) + "\n" if caption.present?
519
+ else
520
+ captionstr = macro('reviewimagecaption', compile_inline(caption)) + "\n" if caption.present?
521
+ end
522
+ captionstr << macro('label', image_label(id))
523
+ @doc_status[:caption] = nil
524
+
471
525
  metrics = parse_metric('latex', metric)
472
526
  # image is always bound here
473
527
  puts "\\begin{reviewimage}%%#{id}"
528
+
529
+ if caption_top?('image') && captionstr
530
+ puts captionstr
531
+ end
532
+
533
+ command = 'reviewincludegraphics'
534
+ if @book.config.check_version('2', exception: false)
535
+ command = 'includegraphics'
536
+ end
537
+
474
538
  if metrics.present?
475
- puts "\\includegraphics[#{metrics}]{#{@chapter.image(id).path}}"
539
+ puts "\\#{command}[#{metrics}]{#{@chapter.image(id).path}}"
476
540
  else
477
- puts "\\includegraphics[width=\\maxwidth]{#{@chapter.image(id).path}}"
541
+ puts "\\#{command}[width=\\maxwidth]{#{@chapter.image(id).path}}"
478
542
  end
479
- @doc_status[:caption] = true
480
- puts macro('caption', compile_inline(caption)) if caption.present?
481
- @doc_status[:caption] = nil
482
- puts macro('label', image_label(id))
543
+
544
+ if !caption_top?('image') && captionstr
545
+ puts captionstr
546
+ end
547
+
483
548
  puts '\end{reviewimage}'
484
549
  end
485
550
 
@@ -493,13 +558,17 @@ module ReVIEW
493
558
  end
494
559
  puts macro('label', image_label(id))
495
560
  @doc_status[:caption] = true
496
- puts macro('caption', compile_inline(caption)) if caption.present?
561
+ if @book.config.check_version('2', exception: false)
562
+ puts macro('caption', compile_inline(caption)) if caption.present?
563
+ else
564
+ puts macro('reviewimagecaption', compile_inline(caption)) if caption.present?
565
+ end
497
566
  @doc_status[:caption] = nil
498
567
  puts '\end{reviewdummyimage}'
499
568
  end
500
569
 
501
570
  def existence(id)
502
- @chapter.image(id).bound? ? 'exist' : 'not exist'
571
+ @chapter.image_bound?(id) ? 'exist' : 'not exist'
503
572
  end
504
573
  private :existence
505
574
 
@@ -540,12 +609,30 @@ module ReVIEW
540
609
  def indepimage(lines, id, caption = nil, metric = nil)
541
610
  metrics = parse_metric('latex', metric)
542
611
 
612
+ captionstr = nil
613
+ if caption.present?
614
+ @doc_status[:caption] = true
615
+ captionstr = macro('reviewindepimagecaption',
616
+ %Q(#{I18n.t('numberless_image')}#{I18n.t('caption_prefix')}#{compile_inline(caption)}))
617
+ @doc_status[:caption] = nil
618
+ end
619
+
543
620
  if @chapter.image(id).path
544
621
  puts "\\begin{reviewimage}%%#{id}"
622
+
623
+ if caption_top?('image') && captionstr
624
+ puts captionstr
625
+ end
626
+
627
+ command = 'reviewincludegraphics'
628
+ if @book.config.check_version('2', exception: false)
629
+ command = 'includegraphics'
630
+ end
631
+
545
632
  if metrics.present?
546
- puts "\\includegraphics[#{metrics}]{#{@chapter.image(id).path}}"
633
+ puts "\\#{command}[#{metrics}]{#{@chapter.image(id).path}}"
547
634
  else
548
- puts "\\includegraphics[width=\\maxwidth]{#{@chapter.image(id).path}}"
635
+ puts "\\#{command}[width=\\maxwidth]{#{@chapter.image(id).path}}"
549
636
  end
550
637
  else
551
638
  warn "image not bound: #{id}"
@@ -556,12 +643,9 @@ module ReVIEW
556
643
  end
557
644
  end
558
645
 
559
- @doc_status[:caption] = true
560
- if caption.present?
561
- puts macro('reviewindepimagecaption',
562
- %Q(#{I18n.t('numberless_image')}#{I18n.t('caption_prefix')}#{compile_inline(caption)}))
646
+ if !caption_top?('image') && captionstr
647
+ puts captionstr
563
648
  end
564
- @doc_status[:caption] = nil
565
649
 
566
650
  if @chapter.image(id).path
567
651
  puts '\end{reviewimage}'
@@ -573,26 +657,35 @@ module ReVIEW
573
657
  alias_method :numberlessimage, :indepimage
574
658
 
575
659
  def table(lines, id = nil, caption = nil)
576
- rows = []
577
- sepidx = nil
578
- lines.each_with_index do |line, idx|
579
- if /\A[\=\{\-\}]{12}/ =~ line
580
- # just ignore
581
- # error "too many table separator" if sepidx
582
- sepidx ||= idx
583
- next
660
+ if caption.present?
661
+ if @book.config.check_version('2', exception: false)
662
+ puts "\\begin{table}[h]%%#{id}"
663
+ else
664
+ puts "\\begin{table}%%#{id}"
584
665
  end
585
- rows.push(line.strip.split(/\t+/).map { |s| s.sub(/\A\./, '') })
586
666
  end
587
- rows = adjust_n_cols(rows)
588
667
 
668
+ sepidx, rows = parse_table_rows(lines)
589
669
  begin
590
- table_header(id, caption) if caption.present?
670
+ if caption_top?('table') && caption.present?
671
+ table_header(id, caption)
672
+ end
591
673
  rescue KeyError
592
674
  error "no such table: #{id}"
593
675
  end
594
- return if rows.empty?
595
676
  table_begin(rows.first.size)
677
+ table_rows(sepidx, rows)
678
+ table_end
679
+ if caption.present?
680
+ unless caption_top?('table')
681
+ table_header(id, caption)
682
+ end
683
+ puts '\end{table}'
684
+ end
685
+ blank
686
+ end
687
+
688
+ def table_rows(sepidx, rows)
596
689
  if sepidx
597
690
  sepidx.times do
598
691
  cno = -1
@@ -619,31 +712,18 @@ module ReVIEW
619
712
  end)
620
713
  end
621
714
  end
622
- table_end
623
715
  end
624
716
 
625
717
  def table_header(id, caption)
626
718
  if id.nil?
627
719
  if caption.present?
628
- @table_caption = true
629
720
  @doc_status[:caption] = true
630
- if @book.config.check_version('2', exception: false)
631
- puts "\\begin{table}[h]%%#{id}"
632
- else
633
- puts "\\begin{table}%%#{id}"
634
- end
635
721
  puts macro('reviewtablecaption*', compile_inline(caption))
636
722
  @doc_status[:caption] = nil
637
723
  end
638
724
  else
639
725
  if caption.present?
640
- @table_caption = true
641
726
  @doc_status[:caption] = true
642
- if @book.config.check_version('2', exception: false)
643
- puts "\\begin{table}[h]%%#{id}"
644
- else
645
- puts "\\begin{table}%%#{id}"
646
- end
647
727
  puts macro('reviewtablecaption', compile_inline(caption))
648
728
  @doc_status[:caption] = nil
649
729
  end
@@ -746,12 +826,9 @@ module ReVIEW
746
826
 
747
827
  def table_end
748
828
  puts macro('end', 'reviewtable')
749
- puts '\end{table}' if @table_caption
750
- @table_caption = nil
751
829
  @tsize = nil
752
830
  @latex_tsize = nil
753
831
  @cellwidth = nil
754
- blank
755
832
  end
756
833
 
757
834
  def emtable(lines, caption = nil)
@@ -759,19 +836,22 @@ module ReVIEW
759
836
  end
760
837
 
761
838
  def imgtable(lines, id, caption = nil, metric = nil)
762
- unless @chapter.image(id).bound?
839
+ unless @chapter.image_bound?(id)
763
840
  warn "image not bound: #{id}"
764
- image_dummy id, caption, lines
841
+ image_dummy(id, caption, lines)
765
842
  return
766
843
  end
767
844
 
845
+ captionstr = nil
768
846
  begin
769
847
  if caption.present?
770
- @table_caption = true
771
- @doc_status[:caption] = true
772
848
  puts "\\begin{table}[h]%%#{id}"
773
- puts macro('reviewimgtablecaption', compile_inline(caption))
849
+ @doc_status[:caption] = true
850
+ captionstr = macro('reviewimgtablecaption', compile_inline(caption))
774
851
  @doc_status[:caption] = nil
852
+ if caption_top?('table')
853
+ puts captionstr
854
+ end
775
855
  end
776
856
  puts macro('label', table_label(id))
777
857
  rescue ReVIEW::KeyError
@@ -779,8 +859,12 @@ module ReVIEW
779
859
  end
780
860
  imgtable_image(id, caption, metric)
781
861
 
782
- puts '\end{table}' if @table_caption
783
- @table_caption = nil
862
+ if caption.present?
863
+ unless caption_top?('table')
864
+ puts captionstr
865
+ end
866
+ puts '\end{table}'
867
+ end
784
868
  blank
785
869
  end
786
870
 
@@ -788,46 +872,61 @@ module ReVIEW
788
872
  metrics = parse_metric('latex', metric)
789
873
  # image is always bound here
790
874
  puts "\\begin{reviewimage}%%#{id}"
875
+
876
+ command = 'reviewincludegraphics'
877
+ if @book.config.check_version('2', exception: false)
878
+ command = 'includegraphics'
879
+ end
880
+
791
881
  if metrics.present?
792
- puts "\\includegraphics[#{metrics}]{#{@chapter.image(id).path}}"
882
+ puts "\\#{command}[#{metrics}]{#{@chapter.image(id).path}}"
793
883
  else
794
- puts "\\includegraphics[width=\\maxwidth]{#{@chapter.image(id).path}}"
884
+ puts "\\#{command}[width=\\maxwidth]{#{@chapter.image(id).path}}"
795
885
  end
796
886
  puts '\end{reviewimage}'
797
887
  end
798
888
 
799
889
  def quote(lines)
800
- latex_block 'quote', lines
890
+ latex_block('quote', lines)
801
891
  end
802
892
 
803
893
  def center(lines)
804
- latex_block 'center', lines
894
+ latex_block('center', lines)
805
895
  end
806
896
 
807
897
  alias_method :centering, :center
808
898
 
809
899
  def flushright(lines)
810
- latex_block 'flushright', lines
900
+ latex_block('flushright', lines)
811
901
  end
812
902
 
813
903
  def texequation(lines, id = nil, caption = '')
814
904
  blank
905
+ captionstr = nil
815
906
 
816
907
  if id
817
908
  puts macro('begin', 'reviewequationblock')
818
909
  if get_chap.nil?
819
- puts macro('reviewequationcaption', "#{I18n.t('equation')}#{I18n.t('format_number_header_without_chapter', [@chapter.equation(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
910
+ captionstr = macro('reviewequationcaption', "#{I18n.t('equation')}#{I18n.t('format_number_header_without_chapter', [@chapter.equation(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
820
911
  else
821
- puts macro('reviewequationcaption', "#{I18n.t('equation')}#{I18n.t('format_number_header', [get_chap, @chapter.equation(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
912
+ captionstr = macro('reviewequationcaption', "#{I18n.t('equation')}#{I18n.t('format_number_header', [get_chap, @chapter.equation(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
822
913
  end
823
914
  end
824
915
 
916
+ if caption_top?('equation') && captionstr
917
+ puts captionstr
918
+ end
919
+
825
920
  puts macro('begin', 'equation*')
826
921
  lines.each do |line|
827
- puts unescape(line)
922
+ puts line
828
923
  end
829
924
  puts macro('end', 'equation*')
830
925
 
926
+ if !caption_top?('equation') && captionstr
927
+ puts captionstr
928
+ end
929
+
831
930
  if id
832
931
  puts macro('end', 'reviewequationblock')
833
932
  end
@@ -853,13 +952,13 @@ module ReVIEW
853
952
  end
854
953
 
855
954
  def comment(lines, comment = nil)
955
+ return true unless @book.config['draft']
856
956
  lines ||= []
857
957
  unless comment.blank?
858
- lines.unshift comment
958
+ lines.unshift(escape(comment))
859
959
  end
860
- return true unless @book.config['draft']
861
960
  str = lines.join('\par ')
862
- puts macro('pdfcomment', escape(str))
961
+ puts macro('pdfcomment', str)
863
962
  end
864
963
 
865
964
  def hr
@@ -968,6 +1067,9 @@ module ReVIEW
968
1067
 
969
1068
  def footnote(id, content)
970
1069
  if @book.config['footnotetext'] || @foottext[id]
1070
+ if @doc_status[:column]
1071
+ warn "//footnote[#{id}] is in the column block. It is recommended to move out of the column block."
1072
+ end
971
1073
  puts macro("footnotetext[#{@chapter.footnote(id).number}]", compile_inline(content.strip))
972
1074
  end
973
1075
  end
@@ -975,7 +1077,7 @@ module ReVIEW
975
1077
  def inline_fn(id)
976
1078
  if @book.config['footnotetext']
977
1079
  macro("footnotemark[#{@chapter.footnote(id).number}]", '')
978
- elsif @doc_status[:caption] || @doc_status[:table] || @doc_status[:column]
1080
+ elsif @doc_status[:caption] || @doc_status[:table] || @doc_status[:column] || @doc_status[:dt]
979
1081
  @foottext[id] = @chapter.footnote(id).number
980
1082
  macro('protect\\footnotemark', '')
981
1083
  else
@@ -988,7 +1090,7 @@ module ReVIEW
988
1090
  BOUTEN = '・'.freeze
989
1091
 
990
1092
  def inline_bou(str)
991
- str.split(//).map { |c| macro('ruby', escape(c), macro('textgt', BOUTEN)) }.join('\allowbreak')
1093
+ macro('reviewbou', escape(str))
992
1094
  end
993
1095
 
994
1096
  def compile_ruby(base, ruby)
@@ -1094,7 +1196,7 @@ module ReVIEW
1094
1196
 
1095
1197
  def inline_hd_chap(chap, id)
1096
1198
  n = chap.headline_index.number(id)
1097
- if chap.number and @book.config['secnolevel'] >= n.split('.').size
1199
+ if n.present? && chap.number && over_secnolevel?(n)
1098
1200
  str = I18n.t('hd_quote', [chap.headline_index.number(id), compile_inline(chap.headline(id).caption)])
1099
1201
  else
1100
1202
  str = I18n.t('hd_quote_without_number', compile_inline(chap.headline(id).caption))
@@ -1145,7 +1247,11 @@ module ReVIEW
1145
1247
 
1146
1248
  def inline_icon(id)
1147
1249
  if @chapter.image(id).path
1148
- macro('includegraphics', @chapter.image(id).path)
1250
+ command = 'reviewincludegraphics'
1251
+ if @book.config.check_version('2', exception: false)
1252
+ command = 'includegraphics'
1253
+ end
1254
+ macro(command, @chapter.image(id).path)
1149
1255
  else
1150
1256
  warn "image not bound: #{id}"
1151
1257
  "\\verb|--[[path = #{id} (#{existence(id)})]]--|"
@@ -1184,7 +1290,12 @@ module ReVIEW
1184
1290
  end
1185
1291
 
1186
1292
  def bibpaper_bibpaper(_id, _caption, lines)
1187
- print split_paragraph(lines).join
1293
+ if @book.config['join_lines_by_lang']
1294
+ print split_paragraph(lines).join("\n\n")
1295
+ else
1296
+ print split_paragraph(lines).map(&:chomp).join("\n")
1297
+ end
1298
+
1188
1299
  puts ''
1189
1300
  end
1190
1301