review 5.1.1 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-tex.yml +5 -1
  3. data/.github/workflows/ruby-win.yml +5 -1
  4. data/.github/workflows/ruby.yml +5 -1
  5. data/.rubocop.yml +6 -2
  6. data/NEWS.ja.md +48 -0
  7. data/NEWS.md +48 -1
  8. data/bin/review-compile +8 -15
  9. data/bin/review-preproc +28 -34
  10. data/doc/config.yml.sample +2 -0
  11. data/doc/writing_vertical.ja.md +6 -0
  12. data/lib/review/builder.rb +34 -40
  13. data/lib/review/compiler.rb +59 -43
  14. data/lib/review/epubmaker.rb +24 -38
  15. data/lib/review/epubmaker/producer.rb +3 -4
  16. data/lib/review/exception.rb +7 -0
  17. data/lib/review/htmlbuilder.rb +51 -20
  18. data/lib/review/idgxmlbuilder.rb +19 -18
  19. data/lib/review/idgxmlmaker.rb +12 -13
  20. data/lib/review/img_math.rb +11 -18
  21. data/lib/review/index_builder.rb +6 -15
  22. data/lib/review/latexbuilder.rb +38 -43
  23. data/lib/review/loggable.rb +27 -0
  24. data/lib/review/logger.rb +48 -0
  25. data/lib/review/makerhelper.rb +5 -1
  26. data/lib/review/markdownbuilder.rb +5 -4
  27. data/lib/review/pdfmaker.rb +23 -21
  28. data/lib/review/plaintextbuilder.rb +8 -8
  29. data/lib/review/preprocessor.rb +94 -296
  30. data/lib/review/preprocessor/directive.rb +35 -0
  31. data/lib/review/preprocessor/line.rb +34 -0
  32. data/lib/review/preprocessor/repository.rb +177 -0
  33. data/lib/review/rstbuilder.rb +1 -1
  34. data/lib/review/template.rb +5 -1
  35. data/lib/review/textmaker.rb +12 -13
  36. data/lib/review/tocprinter.rb +1 -1
  37. data/lib/review/topbuilder.rb +7 -7
  38. data/lib/review/version.rb +1 -1
  39. data/lib/review/webmaker.rb +13 -14
  40. data/review.gemspec +1 -1
  41. data/samples/sample-book/src/lib/tasks/review.rake +3 -1
  42. data/samples/sample-book/src/lib/tasks/z01_copy_sty.rake +2 -1
  43. data/samples/syntax-book/lib/tasks/z01_copy_sty.rake +2 -1
  44. data/templates/latex/review-jlreq/review-base.sty +3 -5
  45. data/templates/latex/review-jlreq/review-jlreq.cls +4 -3
  46. data/templates/latex/review-jsbook/review-base.sty +3 -3
  47. data/templates/latex/review-jsbook/review-jsbook.cls +1 -1
  48. data/test/test_builder.rb +8 -8
  49. data/test/test_epubmaker.rb +13 -8
  50. data/test/test_epubmaker_cmd.rb +13 -2
  51. data/test/test_htmlbuilder.rb +68 -26
  52. data/test/test_idgxmlbuilder.rb +31 -23
  53. data/test/test_latexbuilder.rb +30 -22
  54. data/test/test_latexbuilder_v2.rb +18 -10
  55. data/test/test_plaintextbuilder.rb +30 -22
  56. data/test/test_preprocessor.rb +188 -1
  57. data/test/test_topbuilder.rb +26 -18
  58. metadata +12 -8
@@ -1,8 +1,11 @@
1
1
  require 'fileutils'
2
2
  require 'shellwords'
3
+ require 'review/loggable'
3
4
 
4
5
  module ReVIEW
5
6
  class ImgMath
7
+ include Loggable
8
+
6
9
  def initialize(config, path_name: '_review_math')
7
10
  @config = config
8
11
  @logger = ReVIEW.logger
@@ -50,7 +53,7 @@ module ReVIEW
50
53
  cmd = "latex --interaction=nonstopmode --output-directory=#{tmpdir} #{tex_path} && dvipng -T tight -z9 -o #{img_path} #{dvi_path}"
51
54
  out, status = Open3.capture2e(cmd)
52
55
  unless status.success?
53
- raise ApplicationError, "latex compile error\n\nError log:\n" + out
56
+ raise ApplicationError, "latex compile error\n\nError log:\n#{out}"
54
57
  end
55
58
 
56
59
  img_path
@@ -97,15 +100,13 @@ module ReVIEW
97
100
  when 'dvipng'
98
101
  make_math_images_dvipng(tmpdir, tex_path, math_real_dir)
99
102
  else
100
- error "unknown math converter error. imgmath_options/converter parameter should be 'pdfcrop' or 'dvipng'."
101
- exit 1
103
+ error! "unknown math converter error. imgmath_options/converter parameter should be 'pdfcrop' or 'dvipng'."
102
104
  end
103
105
  rescue CompileError
104
106
  FileUtils.cp([tex_path,
105
107
  File.join(File.dirname(tex_path), '__IMGMATH__.log')],
106
108
  math_real_dir)
107
- error "LaTeX math compile error. See #{math_real_dir}/__IMGMATH__.log for details."
108
- exit 1
109
+ error! "LaTeX math compile error. See #{math_real_dir}/__IMGMATH__.log for details."
109
110
  end
110
111
  end
111
112
  @math_maps.clear
@@ -113,14 +114,6 @@ module ReVIEW
113
114
 
114
115
  private
115
116
 
116
- def error(msg)
117
- @logger.error msg
118
- end
119
-
120
- def warn(msg)
121
- @logger.warn msg
122
- end
123
-
124
117
  def default_imgmath_preamble
125
118
  <<-EOB
126
119
  \\documentclass[uplatex,a3paper,landscape]{jsarticle}
@@ -156,7 +149,7 @@ module ReVIEW
156
149
  if File.exist?(dvi_path)
157
150
  out, status = Open3.capture2e(*[@config['dvicommand'], @config['dvioptions'].shellsplit, dvi_path].flatten.compact)
158
151
  if !status.success? || !File.exist?(pdf_path)
159
- warn "error in #{@config['dvicommand']}. Error log:\n#{out}"
152
+ @logger.error "error in #{@config['dvicommand']}. Error log:\n#{out}"
160
153
  raise CompileError
161
154
  end
162
155
  end
@@ -167,7 +160,7 @@ module ReVIEW
167
160
  end
168
161
  out, status = Open3.capture2e(*args)
169
162
  unless status.success?
170
- warn "error in pdfcrop. Error log:\n#{out}"
163
+ @logger.error "error in pdfcrop. Error log:\n#{out}"
171
164
  raise CompileError
172
165
  end
173
166
  pdf_path = '__IMGMATH__pdfcrop.pdf'
@@ -192,7 +185,7 @@ module ReVIEW
192
185
  end
193
186
  out, status = Open3.capture2e(*args)
194
187
  unless status.success?
195
- warn "error in pdf extracting. Error log:\n#{out}"
188
+ @logger.error "error in pdf extracting. Error log:\n#{out}"
196
189
  raise CompileError
197
190
  end
198
191
 
@@ -209,7 +202,7 @@ module ReVIEW
209
202
  end
210
203
  out, status = Open3.capture2e(*args)
211
204
  unless status.success?
212
- warn "error in pdf pixelizing. Error log:\n#{out}"
205
+ @logger.error "error in pdf pixelizing. Error log:\n#{out}"
213
206
  raise CompileError
214
207
  end
215
208
  end
@@ -235,7 +228,7 @@ module ReVIEW
235
228
  end
236
229
  out, status = Open3.capture2e(*args)
237
230
  unless status.success?
238
- warn "error in dvipng. Error log:\n#{out}"
231
+ @logger.error "error in dvipng. Error log:\n#{out}"
239
232
  raise CompileError
240
233
  end
241
234
  end
@@ -24,9 +24,9 @@ module ReVIEW
24
24
  def check_id(id)
25
25
  if id
26
26
  if id =~ %r![#%\\{}\[\]~/$'"|*?&<>`\s]!
27
- warn "deprecated ID: `#{$&}` in `#{id}`"
27
+ warn "deprecated ID: `#{$&}` in `#{id}`", location: location
28
28
  elsif id.start_with?('.')
29
- warn "deprecated ID: `#{id}` begins from `.`"
29
+ warn "deprecated ID: `#{id}` begins from `.`", location: location
30
30
  end
31
31
  end
32
32
  end
@@ -51,8 +51,7 @@ module ReVIEW
51
51
  end
52
52
 
53
53
  def builder_init_file
54
- @sec_counter = SecCounter.new(5, @chapter)
55
-
54
+ super
56
55
  @headline_stack = []
57
56
 
58
57
  @list_index = ReVIEW::Book::ListIndex.new
@@ -598,17 +597,9 @@ module ReVIEW
598
597
  ''
599
598
  end
600
599
 
601
- def warn(msg)
602
- @logger.warn "#{@location}: #{msg}"
603
- end
604
-
605
- def error(msg = '(no message)')
606
- if msg =~ /builder does not support command/
607
- # ignore
608
- return
609
- end
610
-
611
- super
600
+ ## override
601
+ def error(msg = nil)
602
+ # ignore in indexing
612
603
  end
613
604
 
614
605
  def texequation(_lines, id = nil, _caption = '')
@@ -28,6 +28,7 @@ module ReVIEW
28
28
  end
29
29
 
30
30
  def builder_init_file
31
+ super
31
32
  @chapter.book.image_types = %w[.ai .eps .pdf .tif .tiff .png .bmp .jpg .jpeg .gif]
32
33
  @blank_needed = false
33
34
  @latex_tsize = nil
@@ -35,7 +36,6 @@ module ReVIEW
35
36
  @cellwidth = nil
36
37
  @ol_num = nil
37
38
  @first_line_num = nil
38
- @sec_counter = SecCounter.new(5, @chapter)
39
39
  @foottext = {}
40
40
  setup_index
41
41
  initialize_metachars(@book.config['texcommand'])
@@ -61,7 +61,7 @@ module ReVIEW
61
61
  require 'nkf'
62
62
  @index_mecab = MeCab::Tagger.new(@book.config['pdfmaker']['makeindex_mecab_opts'])
63
63
  rescue LoadError
64
- warn 'not found MeCab'
64
+ warn 'not found MeCab', location: location
65
65
  end
66
66
  end
67
67
 
@@ -156,7 +156,7 @@ module ReVIEW
156
156
  puts macro('label', label) if label
157
157
  end
158
158
  rescue
159
- error "unknown level: #{level}"
159
+ app_error "unknown level: #{level}"
160
160
  end
161
161
 
162
162
  def nonum_begin(level, _label, caption)
@@ -480,7 +480,7 @@ module ReVIEW
480
480
  captionstr = macro('reviewlistcaption', "#{I18n.t('list')}#{I18n.t('format_number_header', [get_chap, @chapter.list(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
481
481
  end
482
482
  rescue KeyError
483
- error "no such list: #{id}"
483
+ app_error "no such list: #{id}"
484
484
  end
485
485
  end
486
486
  end
@@ -613,19 +613,19 @@ module ReVIEW
613
613
  end
614
614
 
615
615
  def image_dummy(id, caption, lines)
616
- warn "image not bound: #{id}"
616
+ warn "image not bound: #{id}", location: location
617
617
  puts '\begin{reviewdummyimage}'
618
- # path = @chapter.image(id).path
619
- puts "--[[path = #{id} (#{existence(id)})]]--"
618
+ puts escape("--[[path = #{id} (#{existence(id)})]]--")
620
619
  lines.each do |line|
620
+ puts "\n"
621
621
  puts detab(line.rstrip)
622
622
  end
623
623
  puts macro('label', image_label(id))
624
624
  @doc_status[:caption] = true
625
625
  if @book.config.check_version('2', exception: false)
626
626
  puts macro('caption', compile_inline(caption)) if caption.present?
627
- else
628
- puts macro('reviewimagecaption', compile_inline(caption)) if caption.present?
627
+ elsif caption.present?
628
+ puts macro('reviewimagecaption', compile_inline(caption))
629
629
  end
630
630
  @doc_status[:caption] = nil
631
631
  puts '\end{reviewdummyimage}'
@@ -700,10 +700,11 @@ module ReVIEW
700
700
  puts "\\#{command}[width=\\maxwidth]{#{@chapter.image(id).path}}"
701
701
  end
702
702
  else
703
- warn "image not bound: #{id}"
703
+ warn "image not bound: #{id}", location: location
704
704
  puts '\begin{reviewdummyimage}'
705
- puts "--[[path = #{escape(id)} (#{existence(id)})]]--"
705
+ puts escape("--[[path = #{escape(id)} (#{existence(id)})]]--")
706
706
  lines.each do |line|
707
+ puts "\n"
707
708
  puts detab(line.rstrip)
708
709
  end
709
710
  end
@@ -736,7 +737,7 @@ module ReVIEW
736
737
  table_header(id, caption)
737
738
  end
738
739
  rescue KeyError
739
- error "no such table: #{id}"
740
+ app_error "no such table: #{id}"
740
741
  end
741
742
  table_begin(rows.first.size)
742
743
  table_rows(sepidx, rows)
@@ -821,7 +822,7 @@ module ReVIEW
821
822
  ret = []
822
823
  s = ''
823
824
  brace = nil
824
- size.split('').each do |ch|
825
+ size.chars.each do |ch|
825
826
  case ch
826
827
  when '|'
827
828
  next
@@ -834,15 +835,11 @@ module ReVIEW
834
835
  ret << s
835
836
  s = ''
836
837
  else
837
- if brace
838
+ if brace || s.empty?
838
839
  s << ch
839
840
  else
840
- if s.empty?
841
- s << ch
842
- else
843
- ret << s
844
- s = ch
845
- end
841
+ ret << s
842
+ s = ch
846
843
  end
847
844
  end
848
845
  end
@@ -902,7 +899,7 @@ module ReVIEW
902
899
 
903
900
  def imgtable(lines, id, caption = nil, metric = nil)
904
901
  unless @chapter.image_bound?(id)
905
- warn "image not bound: #{id}"
902
+ warn "image not bound: #{id}", location: location
906
903
  image_dummy(id, caption, lines)
907
904
  return
908
905
  end
@@ -920,7 +917,7 @@ module ReVIEW
920
917
  end
921
918
  puts macro('label', table_label(id))
922
919
  rescue ReVIEW::KeyError
923
- error "no such table: #{id}"
920
+ app_error "no such table: #{id}"
924
921
  end
925
922
  imgtable_image(id, caption, metric)
926
923
 
@@ -1056,7 +1053,7 @@ module ReVIEW
1056
1053
  title
1057
1054
  end
1058
1055
  rescue KeyError
1059
- error "unknown chapter: #{id}"
1056
+ app_error "unknown chapter: #{id}"
1060
1057
  nofunc_text("[UnknownChapter:#{id}]")
1061
1058
  end
1062
1059
 
@@ -1067,7 +1064,7 @@ module ReVIEW
1067
1064
  @book.chapter_index.number(id)
1068
1065
  end
1069
1066
  rescue KeyError
1070
- error "unknown chapter: #{id}"
1067
+ app_error "unknown chapter: #{id}"
1071
1068
  nofunc_text("[UnknownChapter:#{id}]")
1072
1069
  end
1073
1070
 
@@ -1079,7 +1076,7 @@ module ReVIEW
1079
1076
  title
1080
1077
  end
1081
1078
  rescue KeyError
1082
- error "unknown chapter: #{id}"
1079
+ app_error "unknown chapter: #{id}"
1083
1080
  nofunc_text("[UnknownChapter:#{id}]")
1084
1081
  end
1085
1082
 
@@ -1096,7 +1093,7 @@ module ReVIEW
1096
1093
  macro('reviewlistref', I18n.t('format_number', [get_chap(chapter), chapter.list(id).number]))
1097
1094
  end
1098
1095
  rescue KeyError
1099
- error "unknown list: #{id}"
1096
+ app_error "unknown list: #{id}"
1100
1097
  end
1101
1098
 
1102
1099
  def inline_table(id)
@@ -1107,7 +1104,7 @@ module ReVIEW
1107
1104
  macro('reviewtableref', I18n.t('format_number', [get_chap(chapter), chapter.table(id).number]), table_label(id, chapter))
1108
1105
  end
1109
1106
  rescue KeyError
1110
- error "unknown table: #{id}"
1107
+ app_error "unknown table: #{id}"
1111
1108
  end
1112
1109
 
1113
1110
  def inline_img(id)
@@ -1118,7 +1115,7 @@ module ReVIEW
1118
1115
  macro('reviewimageref', I18n.t('format_number', [get_chap(chapter), chapter.image(id).number]), image_label(id, chapter))
1119
1116
  end
1120
1117
  rescue KeyError
1121
- error "unknown image: #{id}"
1118
+ app_error "unknown image: #{id}"
1122
1119
  end
1123
1120
 
1124
1121
  def inline_eq(id)
@@ -1129,13 +1126,13 @@ module ReVIEW
1129
1126
  macro('reviewequationref', I18n.t('format_number', [get_chap(chapter), chapter.equation(id).number]))
1130
1127
  end
1131
1128
  rescue KeyError
1132
- error "unknown equation: #{id}"
1129
+ app_error "unknown equation: #{id}"
1133
1130
  end
1134
1131
 
1135
1132
  def footnote(id, content)
1136
1133
  if @book.config['footnotetext'] || @foottext[id]
1137
1134
  if @doc_status[:column]
1138
- warn "//footnote[#{id}] is in the column block. It is recommended to move out of the column block."
1135
+ warn "//footnote[#{id}] is in the column block. It is recommended to move out of the column block.", location: location
1139
1136
  end
1140
1137
  puts macro("footnotetext[#{@chapter.footnote(id).number}]", compile_inline(content.strip))
1141
1138
  end
@@ -1151,7 +1148,7 @@ module ReVIEW
1151
1148
  macro('footnote', compile_inline(@chapter.footnote(id).content.strip))
1152
1149
  end
1153
1150
  rescue KeyError
1154
- error "unknown footnote: #{id}"
1151
+ app_error "unknown footnote: #{id}"
1155
1152
  end
1156
1153
 
1157
1154
  BOUTEN = '・'.freeze
@@ -1285,7 +1282,7 @@ module ReVIEW
1285
1282
  I18n.t('column', compile_inline(chapter.column(id).caption)),
1286
1283
  column_label(id, chapter))
1287
1284
  rescue KeyError
1288
- error "unknown column: #{id}"
1285
+ app_error "unknown column: #{id}"
1289
1286
  end
1290
1287
 
1291
1288
  def inline_raw(str) # rubocop:disable Lint/UselessMethodDefinition
@@ -1324,7 +1321,7 @@ module ReVIEW
1324
1321
  end
1325
1322
  macro(command, @chapter.image(id).path)
1326
1323
  else
1327
- warn "image not bound: #{id}"
1324
+ warn "image not bound: #{id}", location: location
1328
1325
  "\\verb|--[[path = #{id} (#{existence(id)})]]--|"
1329
1326
  end
1330
1327
  end
@@ -1377,18 +1374,16 @@ module ReVIEW
1377
1374
  sa.map! do |item|
1378
1375
  if @index_db[item]
1379
1376
  escape_mendex_key(escape_index(@index_db[item])) + '@' + escape_mendex_display(escape_index(escape(item)))
1380
- else
1381
- if item =~ /\A[[:ascii:]]+\Z/ || @index_mecab.nil?
1382
- esc_item = escape_mendex_display(escape_index(escape(item)))
1383
- if esc_item == item
1384
- esc_item
1385
- else
1386
- "#{escape_mendex_key(escape_index(item))}@#{esc_item}"
1387
- end
1377
+ elsif item =~ /\A[[:ascii:]]+\Z/ || @index_mecab.nil?
1378
+ esc_item = escape_mendex_display(escape_index(escape(item)))
1379
+ if esc_item == item
1380
+ esc_item
1388
1381
  else
1389
- yomi = NKF.nkf('-w --hiragana', @index_mecab.parse(item).force_encoding('UTF-8').chomp)
1390
- escape_mendex_key(escape_index(yomi)) + '@' + escape_mendex_display(escape_index(escape(item)))
1382
+ "#{escape_mendex_key(escape_index(item))}@#{esc_item}"
1391
1383
  end
1384
+ else
1385
+ yomi = NKF.nkf('-w --hiragana', @index_mecab.parse(item).force_encoding('UTF-8').chomp)
1386
+ escape_mendex_key(escape_index(yomi)) + '@' + escape_mendex_display(escape_index(escape(item)))
1392
1387
  end
1393
1388
  end
1394
1389
 
@@ -0,0 +1,27 @@
1
+ module ReVIEW
2
+ module Loggable
3
+ attr_reader :logger
4
+
5
+ def error(msg, location: nil)
6
+ logger.error(msg, location: location)
7
+ end
8
+
9
+ def app_error(msg)
10
+ raise ApplicationError, msg
11
+ end
12
+
13
+ def error!(msg, location: nil)
14
+ logger.error(msg, location: location)
15
+
16
+ exit 1
17
+ end
18
+
19
+ def warn(msg, location: nil)
20
+ logger.warn(msg, location: location)
21
+ end
22
+
23
+ def debug(msg, location: nil)
24
+ logger.debug(msg, location: location)
25
+ end
26
+ end
27
+ end
data/lib/review/logger.rb CHANGED
@@ -7,6 +7,30 @@ module ReVIEW
7
7
  self.formatter = ->(severity, _datetime, name, msg) { "#{severity} #{name}: #{msg}\n" }
8
8
  end
9
9
 
10
+ def warn(msg, location: nil)
11
+ if location
12
+ super("#{location}: #{msg}")
13
+ else
14
+ super(msg)
15
+ end
16
+ end
17
+
18
+ def error(msg, location: nil)
19
+ if location
20
+ super("#{location}: #{msg}")
21
+ else
22
+ super(msg)
23
+ end
24
+ end
25
+
26
+ def debug(msg, location: nil)
27
+ if location
28
+ super("#{location}: #{msg}")
29
+ else
30
+ super(msg)
31
+ end
32
+ end
33
+
10
34
  def ttylogger?
11
35
  nil
12
36
  end
@@ -19,6 +43,30 @@ module ReVIEW
19
43
  begin
20
44
  require 'tty-logger'
21
45
  class TTYLogger < ::TTY::Logger
46
+ def warn(msg, location: nil)
47
+ if location
48
+ super("#{location}: #{msg}")
49
+ else
50
+ super(msg)
51
+ end
52
+ end
53
+
54
+ def error(msg, location: nil)
55
+ if location
56
+ super("#{location}: #{msg}")
57
+ else
58
+ super(msg)
59
+ end
60
+ end
61
+
62
+ def debug(msg, location: nil)
63
+ if location
64
+ super("#{location}: #{msg}")
65
+ else
66
+ super(msg)
67
+ end
68
+ end
69
+
22
70
  def ttylogger?
23
71
  true
24
72
  end