review 5.1.1 → 5.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-tex.yml +6 -2
  3. data/.github/workflows/ruby-win.yml +6 -2
  4. data/.github/workflows/ruby.yml +6 -2
  5. data/.rubocop.yml +5 -319
  6. data/NEWS.ja.md +149 -0
  7. data/NEWS.md +149 -1
  8. data/README.md +9 -8
  9. data/bin/review +1 -1
  10. data/bin/review-catalog-converter +15 -15
  11. data/bin/review-check +7 -7
  12. data/bin/review-compile +14 -23
  13. data/bin/review-index +1 -1
  14. data/bin/review-preproc +29 -35
  15. data/bin/review-validate +2 -2
  16. data/doc/config.yml.sample +9 -1
  17. data/doc/config.yml.sample-simple +1 -1
  18. data/doc/format.ja.md +29 -3
  19. data/doc/format.md +32 -3
  20. data/doc/writing_vertical.ja.md +6 -0
  21. data/lib/review/book/base.rb +3 -3
  22. data/lib/review/book/book_unit.rb +13 -3
  23. data/lib/review/book/chapter.rb +1 -1
  24. data/lib/review/book/index.rb +7 -4
  25. data/lib/review/book/part.rb +12 -13
  26. data/lib/review/book/volume.rb +1 -1
  27. data/lib/review/builder.rb +92 -65
  28. data/lib/review/catalog.rb +6 -5
  29. data/lib/review/compiler.rb +76 -57
  30. data/lib/review/configure.rb +5 -2
  31. data/lib/review/epub2html.rb +12 -12
  32. data/lib/review/epubmaker/content.rb +1 -1
  33. data/lib/review/epubmaker/epubcommon.rb +47 -45
  34. data/lib/review/epubmaker/epubv2.rb +2 -1
  35. data/lib/review/epubmaker/epubv3.rb +5 -4
  36. data/lib/review/epubmaker/producer.rb +6 -7
  37. data/lib/review/epubmaker/reviewheaderlistener.rb +1 -1
  38. data/lib/review/epubmaker.rb +56 -67
  39. data/lib/review/exception.rb +7 -0
  40. data/lib/review/extentions/string.rb +1 -1
  41. data/lib/review/htmlbuilder.rb +90 -34
  42. data/lib/review/htmlutils.rb +17 -17
  43. data/lib/review/i18n.rb +3 -3
  44. data/lib/review/i18n.yml +6 -0
  45. data/lib/review/idgxmlbuilder.rb +61 -39
  46. data/lib/review/idgxmlmaker.rb +27 -26
  47. data/lib/review/img_math.rb +12 -18
  48. data/lib/review/index_builder.rb +94 -53
  49. data/lib/review/init.rb +4 -4
  50. data/lib/review/latexbuilder.rb +84 -76
  51. data/lib/review/lineinput.rb +3 -3
  52. data/lib/review/location.rb +1 -1
  53. data/lib/review/loggable.rb +27 -0
  54. data/lib/review/logger.rb +69 -21
  55. data/lib/review/makerhelper.rb +8 -4
  56. data/lib/review/markdownbuilder.rb +21 -12
  57. data/lib/review/pdfmaker.rb +63 -42
  58. data/lib/review/plaintextbuilder.rb +16 -15
  59. data/lib/review/preprocessor/directive.rb +35 -0
  60. data/lib/review/preprocessor/line.rb +34 -0
  61. data/lib/review/preprocessor/repository.rb +177 -0
  62. data/lib/review/preprocessor.rb +94 -296
  63. data/lib/review/rstbuilder.rb +12 -3
  64. data/lib/review/template.rb +5 -1
  65. data/lib/review/textmaker.rb +32 -31
  66. data/lib/review/textutils.rb +5 -6
  67. data/lib/review/tocprinter.rb +12 -7
  68. data/lib/review/topbuilder.rb +96 -19
  69. data/lib/review/update.rb +16 -8
  70. data/lib/review/version.rb +1 -1
  71. data/lib/review/volumeprinter.rb +9 -9
  72. data/lib/review/webmaker.rb +45 -46
  73. data/lib/review/webtocprinter.rb +10 -10
  74. data/lib/review/yamlloader.rb +35 -2
  75. data/review.gemspec +2 -1
  76. data/samples/sample-book/src/config.yml +0 -1
  77. data/samples/sample-book/src/lib/tasks/review.rake +3 -1
  78. data/samples/sample-book/src/lib/tasks/z01_copy_sty.rake +2 -1
  79. data/samples/syntax-book/ch02.re +9 -0
  80. data/samples/syntax-book/lib/tasks/z01_copy_sty.rake +2 -1
  81. data/templates/html/_titlepage.html.erb +9 -17
  82. data/templates/latex/config.erb +3 -0
  83. data/templates/latex/review-jlreq/review-base.sty +4 -5
  84. data/templates/latex/review-jlreq/review-jlreq.cls +39 -5
  85. data/templates/latex/review-jsbook/review-base.sty +9 -3
  86. data/templates/latex/review-jsbook/review-jsbook.cls +32 -5
  87. data/templates/opf/opf_manifest_epubv2.opf.erb +1 -1
  88. data/templates/opf/opf_manifest_epubv3.opf.erb +1 -1
  89. data/test/assets/syntax_book_index_detail.txt +10 -8
  90. data/test/assets/test_template.tex +4 -1
  91. data/test/assets/test_template_backmatter.tex +4 -1
  92. data/test/book_test_helper.rb +10 -10
  93. data/test/test_book_chapter.rb +25 -2
  94. data/test/test_builder.rb +10 -8
  95. data/test/test_epub3maker.rb +3 -3
  96. data/test/test_epubmaker.rb +27 -37
  97. data/test/test_epubmaker_cmd.rb +14 -3
  98. data/test/test_htmlbuilder.rb +111 -31
  99. data/test/test_idgxmlbuilder.rb +41 -33
  100. data/test/test_idgxmlmaker_cmd.rb +1 -1
  101. data/test/test_img_math.rb +11 -2
  102. data/test/test_index.rb +30 -4
  103. data/test/test_latexbuilder.rb +46 -25
  104. data/test/test_latexbuilder_v2.rb +18 -10
  105. data/test/test_markdownbuilder.rb +13 -0
  106. data/test/test_pdfmaker.rb +19 -0
  107. data/test/test_pdfmaker_cmd.rb +10 -10
  108. data/test/test_plaintextbuilder.rb +46 -22
  109. data/test/test_preprocessor.rb +188 -1
  110. data/test/test_rstbuilder.rb +13 -0
  111. data/test/test_textmaker_cmd.rb +1 -1
  112. data/test/test_topbuilder.rb +195 -29
  113. data/test/test_yamlloader.rb +28 -42
  114. metadata +11 -6
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2002-2020 Minero Aoki, Kenshi Muto
1
+ # Copyright (c) 2002-2021 Minero Aoki, Kenshi Muto
2
2
  #
3
3
  # This program is free software.
4
4
  # You can distribute or modify this program under the terms of
@@ -11,6 +11,7 @@ require 'review/textutils'
11
11
  require 'review/compiler'
12
12
  require 'review/sec_counter'
13
13
  require 'review/img_math'
14
+ require 'review/loggable'
14
15
  require 'stringio'
15
16
  require 'fileutils'
16
17
  require 'tempfile'
@@ -19,6 +20,7 @@ require 'csv'
19
20
  module ReVIEW
20
21
  class Builder
21
22
  include TextUtils
23
+ include Loggable
22
24
 
23
25
  CAPTION_TITLES = Compiler.minicolumn_names
24
26
 
@@ -30,7 +32,8 @@ module ReVIEW
30
32
  nil
31
33
  end
32
34
 
33
- attr_accessor :doc_status, :previous_list_type
35
+ attr_accessor :doc_status
36
+ attr_reader :location
34
37
 
35
38
  def initialize(strict = false, *_args, img_math: nil)
36
39
  @strict = strict
@@ -38,8 +41,8 @@ module ReVIEW
38
41
  @logger = ReVIEW.logger
39
42
  @doc_status = {}
40
43
  @dictionary = {}
41
- @previous_list_type = nil
42
44
  @img_math = img_math
45
+ @shown_endnotes = true
43
46
  end
44
47
 
45
48
  def bind(compiler, chapter, location)
@@ -59,11 +62,11 @@ module ReVIEW
59
62
  if @book && @book.config
60
63
  @img_math ||= ReVIEW::ImgMath.new(@book.config)
61
64
  if words_file_path = @book.config['words_file']
62
- if words_file_path.is_a?(String)
63
- words_files = [words_file_path]
64
- else
65
- words_files = words_file_path
66
- end
65
+ words_files = if words_file_path.is_a?(String)
66
+ [words_file_path]
67
+ else
68
+ words_file_path
69
+ end
67
70
  words_files.each do |f|
68
71
  load_words(f)
69
72
  end
@@ -76,7 +79,7 @@ module ReVIEW
76
79
  begin
77
80
  require 'unicode/eaw'
78
81
  rescue LoadError
79
- warn 'not found unicode/eaw. disabled join_lines_by_lang feature.'
82
+ warn 'not found unicode/eaw. disabled join_lines_by_lang feature.', location: @location
80
83
  @book.config['join_lines_by_lang'] = nil
81
84
  end
82
85
  end
@@ -101,11 +104,18 @@ module ReVIEW
101
104
 
102
105
  def check_nest
103
106
  if @children && !@children.empty?
104
- error "//beginchild of #{@children.reverse.join(',')} misses //endchild"
107
+ app_error "#{@location}: //beginchild of #{@children.reverse.join(',')} misses //endchild"
108
+ end
109
+ end
110
+
111
+ def check_printendnotes
112
+ if @shown_endnotes.nil?
113
+ app_error "#{@location}: //endnote is found but //printendnotes is not found."
105
114
  end
106
115
  end
107
116
 
108
117
  def result
118
+ check_printendnotes
109
119
  solve_nest(@output.string)
110
120
  end
111
121
 
@@ -124,11 +134,9 @@ module ReVIEW
124
134
  end
125
135
 
126
136
  def load_words(file)
127
- if File.exist?(file)
128
- if file =~ /\.csv\Z/i
129
- CSV.foreach(file) do |row|
130
- @dictionary[row[0]] = row[1]
131
- end
137
+ if File.exist?(file) && /\.csv\Z/i.match?(file)
138
+ CSV.foreach(file) do |row|
139
+ @dictionary[row[0]] = row[1]
132
140
  end
133
141
  end
134
142
  end
@@ -161,7 +169,7 @@ module ReVIEW
161
169
  list_body(id, lines, lang)
162
170
  list_header(id, caption, lang) unless caption_top?('list')
163
171
  rescue KeyError
164
- error "no such list: #{id}"
172
+ app_error "no such list: #{id}"
165
173
  end
166
174
  end
167
175
 
@@ -171,7 +179,7 @@ module ReVIEW
171
179
  listnum_body(lines, lang)
172
180
  list_header(id, caption, lang) unless caption_top?('list')
173
181
  rescue KeyError
174
- error "no such list: #{id}"
182
+ app_error "no such list: #{id}"
175
183
  end
176
184
  end
177
185
 
@@ -185,7 +193,7 @@ module ReVIEW
185
193
  if @chapter.image_bound?(id)
186
194
  image_image(id, caption, metric)
187
195
  else
188
- warn "image not bound: #{id}" if @strict
196
+ warn "image not bound: #{id}", location: @location if @strict
189
197
  image_dummy(id, caption, lines)
190
198
  end
191
199
  end
@@ -203,7 +211,7 @@ module ReVIEW
203
211
  table_header(id, caption)
204
212
  end
205
213
  rescue KeyError
206
- error "no such table: #{id}"
214
+ app_error "no such table: #{id}"
207
215
  end
208
216
  end
209
217
 
@@ -218,7 +226,7 @@ module ReVIEW
218
226
  when 'verticalbar'
219
227
  Regexp.new('\s*\\' + escape('|') + '\s*')
220
228
  else
221
- error "Unknown value for 'table_row_separator', shold be: tabs, singletab, spaces, verticalbar"
229
+ app_error "Unknown value for 'table_row_separator', shold be: tabs, singletab, spaces, verticalbar"
222
230
  end
223
231
  end
224
232
 
@@ -233,7 +241,7 @@ module ReVIEW
233
241
  rows.push(line.strip.split(table_row_separator_regexp).map { |s| s.sub(/\A\./, '') })
234
242
  end
235
243
  rows = adjust_n_cols(rows)
236
- error 'no rows in the table' if rows.empty?
244
+ app_error 'no rows in the table' if rows.empty?
237
245
  [sepidx, rows]
238
246
  end
239
247
 
@@ -271,17 +279,28 @@ module ReVIEW
271
279
  table(lines, nil, caption)
272
280
  end
273
281
 
274
- # def footnote(id, str)
275
- # @footnotes.push [id, str]
276
- # end
277
- #
278
- # def flush_footnote
279
- # footnote_begin
280
- # @footnotes.each do |id, str|
281
- # footnote_item(id, str)
282
- # end
283
- # footnote_end
284
- # end
282
+ def printendnotes
283
+ @shown_endnotes = true
284
+ endnote_begin
285
+ @chapter.endnotes.each do |en|
286
+ endnote_item(en.id)
287
+ end
288
+ endnote_end
289
+ end
290
+
291
+ def endnote(_id, _str)
292
+ @shown_endnotes = nil
293
+ end
294
+
295
+ def endnote_begin
296
+ end
297
+
298
+ def endnote_end
299
+ end
300
+
301
+ def endnote_item(id)
302
+ puts "(#{@chapter.endnote(id).number}) #{compile_inline(@chapter.endnote(id).content)}"
303
+ end
285
304
 
286
305
  def blankline
287
306
  puts ''
@@ -294,19 +313,19 @@ module ReVIEW
294
313
  def inline_chapref(id)
295
314
  compile_inline(@book.chapter_index.display_string(id))
296
315
  rescue KeyError
297
- error "unknown chapter: #{id}"
316
+ app_error "unknown chapter: #{id}"
298
317
  end
299
318
 
300
319
  def inline_chap(id)
301
320
  @book.chapter_index.number(id)
302
321
  rescue KeyError
303
- error "unknown chapter: #{id}"
322
+ app_error "unknown chapter: #{id}"
304
323
  end
305
324
 
306
325
  def inline_title(id)
307
326
  compile_inline(@book.chapter_index.title(id))
308
327
  rescue KeyError
309
- error "unknown chapter: #{id}"
328
+ app_error "unknown chapter: #{id}"
310
329
  end
311
330
 
312
331
  def inline_list(id)
@@ -317,7 +336,7 @@ module ReVIEW
317
336
  %Q(#{I18n.t('list')}#{I18n.t('format_number_without_chapter', [chapter.list(id).number])})
318
337
  end
319
338
  rescue KeyError
320
- error "unknown list: #{id}"
339
+ app_error "unknown list: #{id}"
321
340
  end
322
341
 
323
342
  def inline_img(id)
@@ -328,7 +347,7 @@ module ReVIEW
328
347
  %Q(#{I18n.t('image')}#{I18n.t('format_number_without_chapter', [chapter.image(id).number])})
329
348
  end
330
349
  rescue KeyError
331
- error "unknown image: #{id}"
350
+ app_error "unknown image: #{id}"
332
351
  end
333
352
 
334
353
  def inline_imgref(id)
@@ -349,7 +368,7 @@ module ReVIEW
349
368
  %Q(#{I18n.t('table')}#{I18n.t('format_number_without_chapter', [chapter.table(id).number])})
350
369
  end
351
370
  rescue KeyError
352
- error "unknown table: #{id}"
371
+ app_error "unknown table: #{id}"
353
372
  end
354
373
 
355
374
  def inline_eq(id)
@@ -360,13 +379,19 @@ module ReVIEW
360
379
  %Q(#{I18n.t('equation')}#{I18n.t('format_number_without_chapter', [chapter.equation(id).number])})
361
380
  end
362
381
  rescue KeyError
363
- error "unknown equation: #{id}"
382
+ app_error "unknown equation: #{id}"
364
383
  end
365
384
 
366
385
  def inline_fn(id)
367
386
  @chapter.footnote(id).content
368
387
  rescue KeyError
369
- error "unknown footnote: #{id}"
388
+ app_error "unknown footnote: #{id}"
389
+ end
390
+
391
+ def inline_endnote(id)
392
+ "(#{@chapter.endnote(id).number})"
393
+ rescue KeyError
394
+ app_error "unknown endnote: #{id}"
370
395
  end
371
396
 
372
397
  def inline_bou(str)
@@ -422,7 +447,7 @@ module ReVIEW
422
447
  inline_hd_chap(@chapter, id)
423
448
  end
424
449
  rescue KeyError
425
- error "unknown headline: #{id}"
450
+ app_error "unknown headline: #{id}"
426
451
  end
427
452
 
428
453
  def inline_column(id)
@@ -436,7 +461,7 @@ module ReVIEW
436
461
  inline_column_chap(@chapter, id)
437
462
  end
438
463
  rescue KeyError
439
- error "unknown column: #{id}"
464
+ app_error "unknown column: #{id}"
440
465
  end
441
466
 
442
467
  def inline_column_chap(chapter, id)
@@ -460,7 +485,7 @@ module ReVIEW
460
485
  if translated
461
486
  escape(translated)
462
487
  else
463
- warn "word not bound: #{s}"
488
+ warn "word not bound: #{s}", location: @location
464
489
  escape("[missing word: #{s}]")
465
490
  end
466
491
  end
@@ -496,18 +521,6 @@ module ReVIEW
496
521
  end
497
522
  end
498
523
 
499
- def warn(msg)
500
- @logger.warn "#{@location}: #{msg}"
501
- end
502
-
503
- def error(msg)
504
- if msg =~ /:\d+: error: /
505
- raise ApplicationError, msg
506
- else
507
- raise ApplicationError, "#{@location}: error: #{msg}"
508
- end
509
- end
510
-
511
524
  def handle_metric(str)
512
525
  str
513
526
  end
@@ -522,8 +535,8 @@ module ReVIEW
522
535
  params = metric.split(/,\s*/)
523
536
  results = []
524
537
  params.each do |param|
525
- if param =~ /\A.+?::/
526
- next unless param =~ /\A#{type}::/
538
+ if /\A.+?::/.match?(param)
539
+ next unless /\A#{type}::/.match?(param)
527
540
 
528
541
  param.sub!(/\A#{type}::/, '')
529
542
  end
@@ -582,7 +595,7 @@ module ReVIEW
582
595
 
583
596
  def check_nested_minicolumn
584
597
  if @doc_status[:minicolumn]
585
- error "#{@location}: nested mini-column is not allowed"
598
+ app_error "#{@location}: nested mini-column is not allowed"
586
599
  end
587
600
  end
588
601
 
@@ -654,7 +667,17 @@ EOTGNUPLOT
654
667
  ext = 'eps'
655
668
  file_path.sub!(/\.pdf\Z/, '.eps')
656
669
  end
657
- system_graph(id, 'java', '-jar', 'plantuml.jar', "-t#{ext}", '-charset', 'UTF-8', tf_path)
670
+ plant_path = nil
671
+ if File.exist?('plantuml.jar')
672
+ plant_path = 'plantuml.jar'
673
+ elsif File.exist?('/usr/share/plantuml/plantuml.jar')
674
+ plant_path = '/usr/share/plantuml/plantuml.jar'
675
+ elsif File.exist?('/usr/share/java/plantuml.jar')
676
+ plant_path = '/usr/share/java/plantuml.jar'
677
+ else
678
+ error!('missing plantuml.jar. Please put plantuml.jar at the working folder.')
679
+ end
680
+ system_graph(id, 'java', '-jar', plant_path, "-t#{ext}", '-charset', 'UTF-8', tf_path)
658
681
  FileUtils.mv("#{tf_path}.#{ext}", file_path)
659
682
  file_path
660
683
  end
@@ -732,18 +755,22 @@ EOTGNUPLOT
732
755
  str
733
756
  end
734
757
 
758
+ def previous_list_type
759
+ @compiler.previous_list_type
760
+ end
761
+
735
762
  def beginchild
736
763
  @children ||= []
737
- unless @previous_list_type
738
- error "//beginchild is shown, but previous element isn't ul, ol, or dl"
764
+ unless previous_list_type
765
+ app_error "#{@location}: //beginchild is shown, but previous element isn't ul, ol, or dl"
739
766
  end
740
- puts "\x01→#{@previous_list_type}←\x01"
741
- @children.push(@previous_list_type)
767
+ puts "\x01→#{previous_list_type}←\x01"
768
+ @children.push(previous_list_type)
742
769
  end
743
770
 
744
771
  def endchild
745
772
  if @children.nil? || @children.empty?
746
- error "//endchild is shown, but any opened //beginchild doesn't exist"
773
+ app_error "#{@location}: //endchild is shown, but any opened //beginchild doesn't exist"
747
774
  else
748
775
  puts "\x01→/#{@children.pop}←\x01"
749
776
  end
@@ -751,7 +778,7 @@ EOTGNUPLOT
751
778
 
752
779
  def caption_top?(type)
753
780
  unless %w[top bottom].include?(@book.config['caption_position'][type])
754
- warn("invalid caption_position/#{type} parameter. 'top' is assumed")
781
+ warn "invalid caption_position/#{type} parameter. 'top' is assumed", location: @location
755
782
  end
756
783
  @book.config['caption_position'][type] != 'bottom'
757
784
  end
@@ -1,13 +1,14 @@
1
1
  require 'yaml'
2
+ require 'date'
2
3
 
3
4
  module ReVIEW
4
5
  class Catalog
5
6
  def initialize(file)
6
- if file.respond_to?(:read)
7
- @yaml = YAML.safe_load(file.read, [Date])
8
- else ## as Object
9
- @yaml = file
10
- end
7
+ @yaml = if file.respond_to?(:read)
8
+ YAMLLoader.safe_load(file.read)
9
+ else ## as Object
10
+ file
11
+ end
11
12
  @yaml ||= {}
12
13
  end
13
14