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) 2013-2020 KADO Masanori, Masayoshi Takahashi, Kenshi Muto
1
+ # Copyright (c) 2013-2021 KADO Masanori, Masayoshi Takahashi, Kenshi Muto
2
2
  #
3
3
  # This program is free software.
4
4
  # You can distribute or modify this program under the terms of
@@ -18,6 +18,7 @@ module ReVIEW
18
18
  end
19
19
 
20
20
  def builder_init_file
21
+ super
21
22
  @noindent = nil
22
23
  @blank_seen = nil
23
24
  @ul_indent = 0
@@ -97,7 +98,7 @@ module ReVIEW
97
98
  end
98
99
 
99
100
  def ul_item_begin(lines)
100
- puts ' ' * (@ul_indent - 1) + '* ' + join_lines_to_paragraph(lines)
101
+ puts (' ' * (@ul_indent - 1)) + '* ' + join_lines_to_paragraph(lines)
101
102
  end
102
103
 
103
104
  def ul_item_end
@@ -245,7 +246,7 @@ module ReVIEW
245
246
  def inline_img(id)
246
247
  "#{I18n.t('image')}#{@chapter.image(id).number}"
247
248
  rescue KeyError
248
- error "unknown image: #{id}"
249
+ app_error "unknown image: #{id}"
249
250
  end
250
251
 
251
252
  def inline_dtp(str)
@@ -254,24 +255,24 @@ module ReVIEW
254
255
 
255
256
  def inline_hd_chap(chap, id)
256
257
  n = chap.headline_index.number(id)
257
- if n.present? && chap.number && over_secnolevel?(n)
258
- str = I18n.t('hd_quote', [n, compile_inline(chap.headline(id).caption)])
259
- else
260
- str = I18n.t('hd_quote_without_number', compile_inline(chap.headline(id).caption))
261
- end
258
+ str = if n.present? && chap.number && over_secnolevel?(n)
259
+ I18n.t('hd_quote', [n, compile_inline(chap.headline(id).caption)])
260
+ else
261
+ I18n.t('hd_quote_without_number', compile_inline(chap.headline(id).caption))
262
+ end
262
263
  if @book.config['chapterlink']
263
264
  if @chapter == chap
264
265
  anchor = 'h' + n.tr('.', '-')
265
266
  %Q(<a href="##{anchor}">#{str}</a>)
266
267
  else
267
- warn 'MARKDOWNBuilder does not support links to other chapters'
268
+ warn 'MARKDOWNBuilder does not support links to other chapters', location: location
268
269
  str
269
270
  end
270
271
  else
271
272
  str
272
273
  end
273
274
  rescue KeyError
274
- error "unknown headline: #{id}"
275
+ app_error "unknown headline: #{id}"
275
276
  end
276
277
 
277
278
  def indepimage(_lines, id, caption = '', _metric = nil)
@@ -360,6 +361,14 @@ module ReVIEW
360
361
  "[^#{id}]"
361
362
  end
362
363
 
364
+ def inline_endnote(id)
365
+ "<sup>#{I18n.t('html_endnote_refmark', @chapter.endnote(id).number)}</sup>"
366
+ end
367
+
368
+ def endnote_item(id)
369
+ puts "#{I18n.t('html_endnote_textmark', @chapter.endnote(id).number)}#{compile_inline(@chapter.endnote(id).content)}"
370
+ end
371
+
363
372
  def inline_br(_str)
364
373
  "\n"
365
374
  end
@@ -400,8 +409,8 @@ module ReVIEW
400
409
  def inline_icon(id)
401
410
  begin
402
411
  "![](#{@chapter.image(id).path.sub(%r{\A\./}, '')})"
403
- rescue
404
- warn "image not bound: #{id}"
412
+ rescue StandardError
413
+ warn "image not bound: #{id}", location: location
405
414
  %Q(<pre>missing image: #{id}</pre>)
406
415
  end
407
416
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2021 Kenshi Muto and Masayoshi Takahashi
1
+ # Copyright (c) 2010-2022 Kenshi Muto and Masayoshi Takahashi
2
2
  #
3
3
  # This program is free software.
4
4
  # You can distribute or modify this program under the terms of
@@ -24,11 +24,12 @@ require 'review/makerhelper'
24
24
  require 'review/template'
25
25
  require 'review/latexbox'
26
26
  require 'review/call_hook'
27
+ require 'review/loggable'
27
28
 
28
29
  module ReVIEW
29
30
  class PDFMaker
30
- include FileUtils
31
31
  include ReVIEW::LaTeXUtils
32
+ include Loggable
32
33
  include ReVIEW::CallHook
33
34
 
34
35
  attr_accessor :config, :basedir
@@ -38,13 +39,14 @@ module ReVIEW
38
39
  @logger = ReVIEW.logger
39
40
  @input_files = Hash.new { |h, key| h[key] = '' }
40
41
  @mastertex = '__REVIEW_BOOK__'
42
+ @compile_errors = nil
41
43
  end
42
44
 
43
45
  def system_with_info(*args)
44
46
  @logger.info args.join(' ')
45
47
  out, status = Open3.capture2e(*args)
46
48
  unless status.success?
47
- @logger.error "execution error\n\nError log:\n" + out
49
+ error "execution error\n\nError log:\n#{out}"
48
50
  end
49
51
  end
50
52
 
@@ -52,19 +54,10 @@ module ReVIEW
52
54
  @logger.info args.join(' ')
53
55
  out, status = Open3.capture2e(*args)
54
56
  unless status.success?
55
- error "failed to run command: #{args.join(' ')}\n\nError log:\n" + out
57
+ error! "failed to run command: #{args.join(' ')}\n\nError log:\n#{out}"
56
58
  end
57
59
  end
58
60
 
59
- def error(msg)
60
- @logger.error msg
61
- exit 1
62
- end
63
-
64
- def warn(msg)
65
- @logger.warn msg
66
- end
67
-
68
61
  def pdf_filepath
69
62
  File.join(@basedir, @config['bookname'] + '.pdf')
70
63
  end
@@ -92,7 +85,7 @@ module ReVIEW
92
85
  if ignore_errors
93
86
  @logger.info 'compile error, but try to generate PDF file'
94
87
  else
95
- error 'compile error, No PDF file output.'
88
+ error! 'compile error, No PDF file output.'
96
89
  end
97
90
  end
98
91
 
@@ -126,11 +119,15 @@ module ReVIEW
126
119
 
127
120
  def execute(*args)
128
121
  cmd_config, yamlfile = parse_opts(args)
129
- error "#{yamlfile} not found." unless File.exist?(yamlfile)
122
+ error! "#{yamlfile} not found." unless File.exist?(yamlfile)
130
123
 
131
- @config = ReVIEW::Configure.create(maker: 'pdfmaker',
132
- yamlfile: yamlfile,
133
- config: cmd_config)
124
+ begin
125
+ @config = ReVIEW::Configure.create(maker: 'pdfmaker',
126
+ yamlfile: yamlfile,
127
+ config: cmd_config)
128
+ rescue ReVIEW::ConfigError => e
129
+ error! e.message
130
+ end
134
131
 
135
132
  I18n.setup(@config['language'])
136
133
  @basedir = File.absolute_path(File.dirname(yamlfile))
@@ -143,11 +140,11 @@ module ReVIEW
143
140
 
144
141
  # version 2 compatibility
145
142
  unless @config['texdocumentclass']
146
- if @config.check_version(2, exception: false)
147
- @config['texdocumentclass'] = ['jsbook', 'uplatex,oneside']
148
- else
149
- @config['texdocumentclass'] = @config['_texdocumentclass']
150
- end
143
+ @config['texdocumentclass'] = if @config.check_version(2, exception: false)
144
+ ['jsbook', 'uplatex,oneside']
145
+ else
146
+ @config['_texdocumentclass']
147
+ end
151
148
  end
152
149
 
153
150
  begin
@@ -155,7 +152,7 @@ module ReVIEW
155
152
  rescue ApplicationError => e
156
153
  raise if @config['debug']
157
154
 
158
- error(e.message)
155
+ error! e.message
159
156
  end
160
157
  end
161
158
 
@@ -200,7 +197,7 @@ module ReVIEW
200
197
  def build_pdf
201
198
  template = template_content
202
199
  Dir.chdir(@path) do
203
- File.open("./#{@mastertex}.tex", 'wb') { |f| f.write template }
200
+ File.write("./#{@mastertex}.tex", template)
204
201
 
205
202
  call_hook('hook_beforetexcompile', Dir.pwd, @basedir, base_dir: @basedir)
206
203
 
@@ -217,7 +214,7 @@ module ReVIEW
217
214
  makeindex_dic = ReVIEW::Configure.values['pdfmaker']['makeindex_dic']
218
215
  else
219
216
  unless @config['texcommand'].present?
220
- error "texcommand isn't defined."
217
+ error! "texcommand isn't defined."
221
218
  end
222
219
  texcommand = @config['texcommand']
223
220
  dvicommand = @config['dvicommand']
@@ -280,6 +277,9 @@ module ReVIEW
280
277
  @config['usepackage'] = ''
281
278
  @config['usepackage'] = "\\usepackage{#{@config['texstyle']}}" if @config['texstyle']
282
279
 
280
+ if @config['pdfmaker']['use_symlink']
281
+ logger.info 'use symlink'
282
+ end
283
283
  copy_images(@config['imagedir'], File.join(@path, @config['imagedir']))
284
284
  copy_sty(File.join(Dir.pwd, 'sty'), @path)
285
285
  copy_sty(File.join(Dir.pwd, 'sty'), @path, 'fd')
@@ -293,7 +293,7 @@ module ReVIEW
293
293
  FileUtils.cp(File.join(@path, "#{@mastertex}.pdf"), pdf_filepath)
294
294
  @logger.success("built #{File.basename(pdf_filepath)}")
295
295
  ensure
296
- remove_entry_secure(@path) unless @config['debug']
296
+ FileUtils.remove_entry_secure(@path) unless @config['debug']
297
297
  end
298
298
  end
299
299
 
@@ -301,10 +301,10 @@ module ReVIEW
301
301
  @logger.info "compiling #{filename}.tex"
302
302
  begin
303
303
  @converter.convert(filename + '.re', File.join(@path, filename + '.tex'))
304
- rescue => e
304
+ rescue StandardError => e
305
305
  @compile_errors = true
306
- warn "compile error in #{filename}.tex (#{e.class})"
307
- warn e.message
306
+ error "compile error in #{filename}.tex (#{e.class})"
307
+ error e.message
308
308
  end
309
309
  end
310
310
 
@@ -314,16 +314,24 @@ module ReVIEW
314
314
  return unless File.exist?(from)
315
315
 
316
316
  Dir.mkdir(to)
317
- ReVIEW::MakerHelper.copy_images_to_dir(from, to)
317
+ if @config['pdfmaker']['use_symlink']
318
+ ReVIEW::MakerHelper.copy_images_to_dir(from, to, use_symlink: true)
319
+ else
320
+ ReVIEW::MakerHelper.copy_images_to_dir(from, to)
321
+ end
318
322
  end
319
323
 
320
324
  def make_custom_page(file)
325
+ if file.nil?
326
+ return nil
327
+ end
328
+
321
329
  file_sty = file.to_s.sub(/\.[^.]+\Z/, '.tex')
322
330
  if File.exist?(file_sty)
323
- return File.read(file_sty)
331
+ File.read(file_sty)
332
+ else
333
+ warn "File #{file_sty} is not found."
324
334
  end
325
-
326
- nil
327
335
  end
328
336
 
329
337
  def join_with_separator(value, sep)
@@ -373,9 +381,9 @@ module ReVIEW
373
381
  items.each_with_index do |item, rev|
374
382
  editstr = edit == 0 ? ReVIEW::I18n.t('first_edition') : ReVIEW::I18n.t('nth_edition', (edit + 1).to_s)
375
383
  revstr = ReVIEW::I18n.t('nth_impression', (rev + 1).to_s)
376
- if item =~ /\A\d+-\d+-\d+\Z/
384
+ if /\A\d+-\d+-\d+\Z/.match?(item)
377
385
  buf << ReVIEW::I18n.t('published_by1', [date_to_s(item), editstr + revstr])
378
- elsif item =~ /\A(\d+-\d+-\d+)[\s ](.+)/
386
+ elsif /\A(\d+-\d+-\d+)[\s ](.+)/.match?(item)
379
387
  # custom date with string
380
388
  item.match(/\A(\d+-\d+-\d+)[\s ](.+)/) { |m| buf << ReVIEW::I18n.t('published_by3', [date_to_s(m[1]), m[2]]) }
381
389
  else
@@ -442,6 +450,10 @@ module ReVIEW
442
450
  end
443
451
  end
444
452
 
453
+ if @config['coverimage'] && !File.exist?(File.join(@config['imagedir'], @config['coverimage']))
454
+ raise ReVIEW::ConfigError, "coverimage #{@config['coverimage']} is not found."
455
+ end
456
+
445
457
  @locale_latex = {}
446
458
  part_tuple = I18n.get('part').split(/%[A-Za-z]{1,3}/, 2)
447
459
  chapter_tuple = I18n.get('chapter').split(/%[A-Za-z]{1,3}/, 2)
@@ -457,7 +469,7 @@ module ReVIEW
457
469
  begin
458
470
  @boxsetting = ReVIEW::LaTeXBox.new.tcbox(@config)
459
471
  rescue ReVIEW::ConfigError => e
460
- error e
472
+ error! e
461
473
  end
462
474
  end
463
475
  end
@@ -475,17 +487,24 @@ module ReVIEW
475
487
 
476
488
  def template_content
477
489
  template_dir = ReVIEW::Template::TEMPLATE_DIR
478
- if @config.check_version('2', exception: false)
479
- template_path = './latex-compat2/layout.tex.erb'
480
- else
481
- template_path = './latex/layout.tex.erb'
482
- end
490
+ template_path = if @config.check_version('2', exception: false)
491
+ './latex-compat2/layout.tex.erb'
492
+ else
493
+ './latex/layout.tex.erb'
494
+ end
483
495
  layout_file = File.join(@basedir, 'layouts', 'layout.tex.erb')
484
496
  if File.exist?(layout_file)
485
497
  template_dir = @basedir
486
498
  template_path = 'layouts/layout.tex.erb'
487
499
  end
488
500
  ReVIEW::Template.generate(path: template_path, mode: '-', binding: binding, template_dir: template_dir)
501
+ rescue StandardError => e
502
+ if defined?(e.full_message)
503
+ error! "template or configuration error: #{e.full_message(highlight: false)}"
504
+ else
505
+ # <= Ruby 2.4
506
+ error! "template or configuration error: #{e.message}"
507
+ end
489
508
  end
490
509
 
491
510
  def copy_sty(dirname, copybase, extname = 'sty')
@@ -503,6 +522,8 @@ module ReVIEW
503
522
  File.open(File.join(copybase, fname.sub(/\.erb\Z/, '')), 'w') do |f|
504
523
  f.print erb_content(File.join(dirname, fname))
505
524
  end
525
+ elsif @config['pdfmaker']['use_symlink']
526
+ FileUtils.ln_s(File.join(dirname, fname), copybase)
506
527
  else
507
528
  FileUtils.cp(File.join(dirname, fname), copybase)
508
529
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018-2020 Kenshi Muto
1
+ # Copyright (c) 2018-2021 Kenshi Muto
2
2
  #
3
3
  # This program is free software.
4
4
  # You can distribute or modify this program under the terms of
@@ -42,12 +42,12 @@ module ReVIEW
42
42
  end
43
43
 
44
44
  def builder_init_file
45
+ super
45
46
  @section = 0
46
47
  @subsection = 0
47
48
  @subsubsection = 0
48
49
  @subsubsubsection = 0
49
50
  @blank_seen = true
50
- @sec_counter = SecCounter.new(5, @chapter)
51
51
  end
52
52
  private :builder_init_file
53
53
 
@@ -74,6 +74,7 @@ module ReVIEW
74
74
  private :blank
75
75
 
76
76
  def result
77
+ check_printendnotes
77
78
  solve_nest(@output.string)
78
79
  end
79
80
 
@@ -85,11 +86,11 @@ module ReVIEW
85
86
  if l =~ /\A\x01→(dl|ul|ol)←\x01/
86
87
  clevel.push($1)
87
88
  lines.push("\x01→END←\x01")
88
- elsif l =~ %r{\A\x01→/(dl|ul|ol)←\x01}
89
+ elsif %r{\A\x01→/(dl|ul|ol)←\x01}.match?(l)
89
90
  clevel.pop
90
91
  lines.push("\x01→END←\x01")
91
92
  else
92
- lines.push("\t" * clevel.size + l)
93
+ lines.push(("\t" * clevel.size) + l)
93
94
  end
94
95
  end
95
96
 
@@ -169,7 +170,7 @@ module ReVIEW
169
170
  list_header(id, caption, lang)
170
171
  end
171
172
  rescue KeyError
172
- error "no such list: #{id}"
173
+ app_error "no such list: #{id}"
173
174
  end
174
175
  blank
175
176
  end
@@ -213,14 +214,14 @@ module ReVIEW
213
214
 
214
215
  def emlistnum(lines, caption = nil, _lang = nil)
215
216
  blank
216
- if caption_top?('list')
217
- puts compile_inline(caption) if caption.present?
217
+ if caption_top?('list') && caption.present?
218
+ puts compile_inline(caption)
218
219
  end
219
220
  lines.each_with_index do |line, i|
220
221
  puts((i + 1).to_s.rjust(2) + ": #{line}")
221
222
  end
222
- unless caption_top?('list')
223
- puts compile_inline(caption) if caption.present?
223
+ if !caption_top?('list') && caption.present?
224
+ puts compile_inline(caption)
224
225
  end
225
226
  blank
226
227
  end
@@ -238,7 +239,7 @@ module ReVIEW
238
239
  list_header(id, caption, lang)
239
240
  end
240
241
  rescue KeyError
241
- error "no such list: #{id}"
242
+ app_error "no such list: #{id}"
242
243
  end
243
244
  blank
244
245
  end
@@ -337,7 +338,7 @@ module ReVIEW
337
338
  def inline_fn(id)
338
339
  " 注#{@chapter.footnote(id).number} "
339
340
  rescue KeyError
340
- error "unknown footnote: #{id}"
341
+ app_error "unknown footnote: #{id}"
341
342
  end
342
343
 
343
344
  def compile_ruby(base, _ruby)
@@ -401,7 +402,7 @@ module ReVIEW
401
402
  def inline_bib(id)
402
403
  %Q(#{@chapter.bibpaper(id).number} )
403
404
  rescue KeyError
404
- error "unknown bib: #{id}"
405
+ app_error "unknown bib: #{id}"
405
406
  end
406
407
 
407
408
  def inline_hd_chap(chap, id)
@@ -412,7 +413,7 @@ module ReVIEW
412
413
  I18n.t('hd_quote_without_number', compile_inline(chap.headline(id).caption))
413
414
  end
414
415
  rescue KeyError
415
- error "unknown headline: #{id}"
416
+ app_error "unknown headline: #{id}"
416
417
  end
417
418
 
418
419
  def noindent
@@ -680,7 +681,7 @@ module ReVIEW
680
681
  if @book.config['chapref']
681
682
  chs2 = @book.config['chapref'].split(',')
682
683
  if chs2.size != 3
683
- error '--chapsplitter must have exactly 3 parameters with comma.'
684
+ app_error '--chapsplitter must have exactly 3 parameters with comma.'
684
685
  end
685
686
  chs = chs2
686
687
  end
@@ -694,7 +695,7 @@ module ReVIEW
694
695
  end
695
696
  end
696
697
  rescue KeyError
697
- error "unknown chapter: #{id}"
698
+ app_error "unknown chapter: #{id}"
698
699
  end
699
700
 
700
701
  def source(lines, caption = nil, _lang = nil)
@@ -0,0 +1,35 @@
1
+ # Copyright (c) 2010-2021 Minero Aoki, Kenshi Muto
2
+ #
3
+ # This program is free software.
4
+ # You can distribute or modify this program under the terms of
5
+ # the GNU LGPL, Lesser General Public License version 2.1.
6
+ # For details of the GNU LGPL, see the file "COPYING".
7
+ #
8
+
9
+ module ReVIEW
10
+ class Preprocessor
11
+ class Directive
12
+ def initialize(op, args, opts)
13
+ @op = op
14
+ @args = args
15
+ @opts = opts
16
+ end
17
+
18
+ attr_reader :op
19
+ attr_reader :args
20
+ attr_reader :opts
21
+
22
+ def arg
23
+ @args.first
24
+ end
25
+
26
+ def opt
27
+ @opts.first
28
+ end
29
+
30
+ def [](key)
31
+ @opts[key]
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,34 @@
1
+ # Copyright (c) 2010-2021 Minero Aoki, Kenshi Muto
2
+ #
3
+ # This program is free software.
4
+ # You can distribute or modify this program under the terms of
5
+ # the GNU LGPL, Lesser General Public License version 2.1.
6
+ # For details of the GNU LGPL, see the file "COPYING".
7
+ #
8
+
9
+ module ReVIEW
10
+ class Preprocessor
11
+ class Line
12
+ def initialize(number, string)
13
+ @number = number
14
+ @string = string
15
+ end
16
+
17
+ attr_reader :number
18
+ attr_reader :string
19
+ alias_method :to_s, :string
20
+
21
+ def edit
22
+ self.class.new(@number, yield(@string))
23
+ end
24
+
25
+ def empty?
26
+ @string.strip.empty?
27
+ end
28
+
29
+ def num_indent
30
+ @string.slice(/\A\s*/).size
31
+ end
32
+ end
33
+ end
34
+ end