review 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +20 -5
  3. data/.travis.yml +2 -1
  4. data/NEWS.ja.md +93 -0
  5. data/NEWS.md +77 -0
  6. data/README.md +1 -1
  7. data/bin/review +38 -12
  8. data/bin/review-compile +106 -88
  9. data/bin/review-epubmaker +6 -1
  10. data/bin/review-init +21 -1
  11. data/bin/review-textmaker +16 -0
  12. data/doc/config.yml.sample +6 -1
  13. data/doc/format.ja.md +23 -0
  14. data/doc/format.md +20 -2
  15. data/doc/quickstart.ja.md +8 -4
  16. data/doc/quickstart.md +11 -8
  17. data/lib/review/book/base.rb +29 -18
  18. data/lib/review/book/index.rb +10 -5
  19. data/lib/review/builder.rb +58 -33
  20. data/lib/review/catalog.rb +30 -0
  21. data/lib/review/compiler.rb +53 -19
  22. data/lib/review/configure.rb +15 -14
  23. data/lib/review/epubmaker.rb +15 -4
  24. data/lib/review/htmlbuilder.rb +56 -24
  25. data/lib/review/idgxmlbuilder.rb +17 -7
  26. data/lib/review/latexbuilder.rb +113 -38
  27. data/lib/review/markdownbuilder.rb +12 -5
  28. data/lib/review/md2inaobuilder.rb +3 -1
  29. data/lib/review/pdfmaker.rb +23 -9
  30. data/lib/review/plaintextbuilder.rb +683 -0
  31. data/lib/review/rstbuilder.rb +30 -10
  32. data/lib/review/textmaker.rb +158 -0
  33. data/lib/review/textutils.rb +10 -1
  34. data/lib/review/topbuilder.rb +32 -417
  35. data/lib/review/version.rb +1 -1
  36. data/lib/review/webmaker.rb +29 -8
  37. data/review.gemspec +3 -4
  38. data/templates/html/layout-xhtml1.html.erb +0 -2
  39. data/templates/latex/layout.tex.erb +6 -4
  40. data/templates/web/html/layout-xhtml1.html.erb +0 -2
  41. data/test/book_test_helper.rb +1 -0
  42. data/test/run_test.rb +1 -1
  43. data/test/sample-book/src/Rakefile +19 -3
  44. data/test/syntax-book/Rakefile +19 -3
  45. data/test/test_catalog.rb +45 -0
  46. data/test/test_compiler.rb +8 -2
  47. data/test/test_htmlbuilder.rb +22 -0
  48. data/test/test_idgxmlbuilder.rb +22 -0
  49. data/test/test_index.rb +31 -0
  50. data/test/test_latexbuilder.rb +48 -16
  51. data/test/test_plaintextbuilder.rb +390 -0
  52. data/test/test_textutils.rb +2 -0
  53. data/test/test_topbuilder.rb +23 -1
  54. metadata +13 -7
@@ -48,5 +48,35 @@ module ReVIEW
48
48
  return '' unless @yaml['POSTDEF']
49
49
  @yaml['POSTDEF'].join("\n")
50
50
  end
51
+
52
+ def validate!(basedir)
53
+ filenames = []
54
+ if predef.present?
55
+ filenames.concat(predef.split(/\n/))
56
+ end
57
+ parts_with_chaps.each do |chap|
58
+ if chap.is_a?(Hash)
59
+ chap.each_key do |part|
60
+ if File.extname(part) == '.re'
61
+ filenames.push(part)
62
+ end
63
+ end
64
+ filenames.concat(chap.values.flatten)
65
+ else
66
+ filenames.push(chap)
67
+ end
68
+ end
69
+ if appendix.present?
70
+ filenames.concat(appendix.split(/\n/))
71
+ end
72
+ if postdef.present?
73
+ filenames.concat(postdef.split(/\n/))
74
+ end
75
+ filenames.each do |filename|
76
+ unless File.exist?(File.join(basedir, filename))
77
+ raise FileNotFound, "file not found in catalog.yml: #{basedir}/#{filename}"
78
+ end
79
+ end
80
+ end
51
81
  end
52
82
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2009-2017 Minero Aoki, Kenshi Muto
1
+ # Copyright (c) 2009-2018 Minero Aoki, Kenshi Muto
2
2
  # Copyright (c) 2002-2007 Minero Aoki
3
3
  #
4
4
  # This program is free software.
@@ -59,8 +59,12 @@ module ReVIEW
59
59
  attr_reader :name
60
60
 
61
61
  def check_args(args)
62
- raise CompileError, "wrong # of parameters (block command //#{@name}, expect #{@argc_spec} but #{args.size})" unless @argc_spec === args.size
63
- @checker.call(*args) if @checker
62
+ unless @argc_spec === args.size
63
+ raise CompileError, "wrong # of parameters (block command //#{@name}, expect #{@argc_spec} but #{args.size})"
64
+ end
65
+ if @checker
66
+ @checker.call(*args)
67
+ end
64
68
  end
65
69
 
66
70
  def min_argc
@@ -161,7 +165,7 @@ module ReVIEW
161
165
 
162
166
  defsingle :footnote, 2
163
167
  defsingle :noindent, 0
164
- defsingle :linebreak, 0
168
+ defsingle :blankline, 0
165
169
  defsingle :pagebreak, 0
166
170
  defsingle :hr, 0
167
171
  defsingle :parasep, 0
@@ -286,19 +290,29 @@ module ReVIEW
286
290
  index = level - 1
287
291
  if tag
288
292
  if tag !~ %r{\A/}
289
- warn 'headline is empty.' if caption.empty?
293
+ if caption.empty?
294
+ warn 'headline is empty.'
295
+ end
290
296
  close_current_tagged_section(level)
291
297
  open_tagged_section(tag, level, label, caption)
292
298
  else
293
299
  open_tag = tag[1..-1]
294
300
  prev_tag_info = @tagged_section.pop
295
- error "#{open_tag} is not opened." if prev_tag_info.nil? || prev_tag_info.first != open_tag
301
+ if prev_tag_info.nil? || prev_tag_info.first != open_tag
302
+ error "#{open_tag} is not opened."
303
+ end
296
304
  close_tagged_section(*prev_tag_info)
297
305
  end
298
306
  else
299
- warn 'headline is empty.' if caption.empty?
300
- @headline_indexs = @headline_indexs[0..index] if @headline_indexs.size > (index + 1)
301
- @headline_indexs[index] = 0 if @headline_indexs[index].nil?
307
+ if caption.empty?
308
+ warn 'headline is empty.'
309
+ end
310
+ if @headline_indexs.size > (index + 1)
311
+ @headline_indexs = @headline_indexs[0..index]
312
+ end
313
+ if @headline_indexs[index].nil?
314
+ @headline_indexs[index] = 0
315
+ end
302
316
  @headline_indexs[index] += 1
303
317
  close_current_tagged_section(level)
304
318
  @strategy.headline level, label, caption
@@ -340,7 +354,9 @@ module ReVIEW
340
354
  end
341
355
 
342
356
  def close_all_tagged_section
343
- close_tagged_section(* @tagged_section.pop) until @tagged_section.empty?
357
+ until @tagged_section.empty?
358
+ close_tagged_section(* @tagged_section.pop)
359
+ end
344
360
  end
345
361
 
346
362
  def compile_ulist(f)
@@ -349,7 +365,9 @@ module ReVIEW
349
365
  next if line =~ /\A\#@/
350
366
 
351
367
  buf = [text(line.sub(/\*+/, '').strip)]
352
- f.while_match(/\A\s+(?!\*)\S/) { |cont| buf.push text(cont.strip) }
368
+ f.while_match(/\A\s+(?!\*)\S/) do |cont|
369
+ buf.push text(cont.strip)
370
+ end
353
371
 
354
372
  line =~ /\A\s+(\*+)/
355
373
  current_level = $1.size
@@ -392,7 +410,9 @@ module ReVIEW
392
410
 
393
411
  num = line.match(/(\d+)\./)[1]
394
412
  buf = [text(line.sub(/\d+\./, '').strip)]
395
- f.while_match(/\A\s+(?!\d+\.)\S/) { |cont| buf.push text(cont.strip) }
413
+ f.while_match(/\A\s+(?!\d+\.)\S/) do |cont|
414
+ buf.push text(cont.strip)
415
+ end
396
416
  @strategy.ol_item buf, num
397
417
  end
398
418
  @strategy.ol_end
@@ -402,7 +422,8 @@ module ReVIEW
402
422
  @strategy.dl_begin
403
423
  while /\A\s*:/ =~ f.peek
404
424
  @strategy.dt text(f.gets.sub(/\A\s*:/, '').strip)
405
- @strategy.dd(f.break(/\A(\S|\s*:|\s+\d+\.\s|\s+\*\s)/).map { |line| text(line.strip) })
425
+ desc = f.break(/\A(\S|\s*:|\s+\d+\.\s|\s+\*\s)/).map { |line| text(line.strip) }
426
+ @strategy.dd(desc)
406
427
  f.skip_blank_lines
407
428
  f.skip_comment_lines
408
429
  end
@@ -423,8 +444,9 @@ module ReVIEW
423
444
  name = line.slice(/[a-z]+/).to_sym
424
445
  ignore_inline = (name == :embed)
425
446
  args = parse_args(line.sub(%r{\A//[a-z]+}, '').rstrip.chomp('{'), name)
447
+ @strategy.doc_status[name] = true
426
448
  lines = block_open?(line) ? read_block(f, ignore_inline) : nil
427
-
449
+ @strategy.doc_status[name] = nil
428
450
  [name, args, lines]
429
451
  end
430
452
 
@@ -483,7 +505,9 @@ module ReVIEW
483
505
  if syntax.block_allowed?
484
506
  compile_block syntax, args, lines
485
507
  else
486
- error "block is not allowed for command //#{syntax.name}; ignore" if lines
508
+ if lines
509
+ error "block is not allowed for command //#{syntax.name}; ignore"
510
+ end
487
511
  compile_single syntax, args
488
512
  end
489
513
  end
@@ -497,7 +521,9 @@ module ReVIEW
497
521
  end
498
522
 
499
523
  def default_block(syntax)
500
- error "block is required for //#{syntax.name}; use empty block" if syntax.block_required?
524
+ if syntax.block_required?
525
+ error "block is required for //#{syntax.name}; use empty block"
526
+ end
501
527
  []
502
528
  end
503
529
 
@@ -516,7 +542,11 @@ module ReVIEW
516
542
  def text(str)
517
543
  return '' if str.empty?
518
544
  words = replace_fence(str).split(/(@<\w+>\{(?:[^\}\\]|\\.)*?\})/, -1)
519
- words.each { |w| error "`@<xxx>' seen but is not valid inline op: #{w}" if w.scan(/@<\w+>/).size > 1 && !/\A@<raw>/.match(w) }
545
+ words.each do |w|
546
+ if w.scan(/@<\w+>/).size > 1 && !/\A@<raw>/.match(w)
547
+ error "`@<xxx>' seen but is not valid inline op: #{w}"
548
+ end
549
+ end
520
550
  result = @strategy.nofunc_text(words.shift)
521
551
  until words.empty?
522
552
  result << compile_inline(words.shift.gsub(/\\\}/, '}').gsub(/\\\\/, '\\'))
@@ -530,8 +560,12 @@ module ReVIEW
530
560
 
531
561
  def compile_inline(str)
532
562
  op, arg = /\A@<(\w+)>\{(.*?)\}\z/.match(str).captures
533
- raise CompileError, "no such inline op: #{op}" unless inline_defined?(op)
534
- raise "strategy does not support inline op: @<#{op}>" unless @strategy.respond_to?("inline_#{op}")
563
+ unless inline_defined?(op)
564
+ raise CompileError, "no such inline op: #{op}"
565
+ end
566
+ unless @strategy.respond_to?("inline_#{op}")
567
+ raise "strategy does not support inline op: @<#{op}>"
568
+ end
535
569
  @strategy.__send__("inline_#{op}", arg)
536
570
  rescue => err
537
571
  error err.message
@@ -53,23 +53,24 @@ module ReVIEW
53
53
  'ext' => '.re',
54
54
  'image_dir' => 'images',
55
55
  'image_types' => %w[.ai .psd .eps .pdf .tif .tiff .png .bmp .jpg .jpeg .gif .svg],
56
- 'image_scale2width' => true, # for LaTeX
57
56
  'bib_file' => 'bib.re',
58
57
  'colophon_order' => %w[aut csl trl dsr ill cov edt pbl contact prt],
59
58
  'externallink' => true,
60
- 'tableopt' => nil, # for IDGXML
61
- 'listinfo' => nil, # for IDGXML
62
- 'nolf' => true, # for IDGXML
63
- 'chapref' => nil, # for IDGXML
64
- 'structuredxml' => nil, # for IDGXML
65
- 'pt_to_mm_unit' => 0.3528, # for IDGXML (DTP: 1pt = 0.3528mm, JIS: 1pt = 0.3514mm)
66
-
67
- 'footnotetext' => nil, # for LaTeX
68
- 'texcommand' => 'uplatex', # for LaTeX
69
- 'texdocumentclass' => ['jsbook', 'uplatex,oneside'], # for LaTeX
70
- 'dvicommand' => 'dvipdfmx', # for LaTeX
71
- 'dvioptions' => '-d 5', # for LaTeX
72
-
59
+ # for IDGXML
60
+ 'tableopt' => nil,
61
+ 'listinfo' => nil,
62
+ 'nolf' => true,
63
+ 'chapref' => nil,
64
+ 'structuredxml' => nil,
65
+ 'pt_to_mm_unit' => 0.3528, # DTP: 1pt = 0.3528mm, JIS: 1pt = 0.3514mm
66
+ # for LaTeX
67
+ 'image_scale2width' => true,
68
+ 'footnotetext' => nil,
69
+ 'texcommand' => 'uplatex',
70
+ 'texdocumentclass' => ['jsbook', 'uplatex,oneside'],
71
+ 'dvicommand' => 'dvipdfmx',
72
+ 'dvioptions' => '-d 5',
73
+ # for PDFMaker
73
74
  'pdfmaker' => {
74
75
  'makeindex' => nil, # Make index page
75
76
  'makeindex_command' => 'mendex', # works only when makeindex is true
@@ -50,7 +50,13 @@ module ReVIEW
50
50
 
51
51
  def load_yaml(yamlfile)
52
52
  loader = ReVIEW::YAMLLoader.new
53
- @config = ReVIEW::Configure.values.deep_merge(loader.load_file(yamlfile))
53
+ @config = ReVIEW::Configure.values
54
+ begin
55
+ @config.deep_merge!(loader.load_file(yamlfile))
56
+ rescue => e
57
+ error "yaml error #{e.message}"
58
+ end
59
+
54
60
  @producer = Producer.new(@config)
55
61
  @producer.load(yamlfile)
56
62
  @config = @producer.config
@@ -134,8 +140,11 @@ module ReVIEW
134
140
  log('Call ePUB producer.')
135
141
  @producer.produce("#{bookname}.epub", basetmpdir, epubtmpdir)
136
142
  log('Finished.')
143
+ rescue ApplicationError => e
144
+ raise if @config['debug']
145
+ error(e.message)
137
146
  ensure
138
- FileUtils.remove_entry_secure basetmpdir unless @config['debug']
147
+ FileUtils.remove_entry_secure(basetmpdir) unless @config['debug']
139
148
  end
140
149
  end
141
150
 
@@ -364,7 +373,8 @@ module ReVIEW
364
373
  def write_info_body(basetmpdir, _id, filename, ispart = nil, chaptype = nil)
365
374
  headlines = []
366
375
  path = File.join(basetmpdir, filename)
367
- Document.parse_stream(File.new(path), ReVIEWHeaderListener.new(headlines))
376
+ htmlio = File.new(path)
377
+ Document.parse_stream(htmlio, ReVIEWHeaderListener.new(headlines))
368
378
  properties = detect_properties(path)
369
379
  prop_str = ''
370
380
  prop_str = ',properties=' + properties.join(' ') if properties.present?
@@ -378,6 +388,7 @@ module ReVIEW
378
388
  first = nil
379
389
  end
380
390
  end
391
+ htmlio.close
381
392
  end
382
393
 
383
394
  def push_contents(_basetmpdir)
@@ -435,7 +446,7 @@ module ReVIEW
435
446
  @body << %Q(<h1 class="tp-title">#{CGI.escapeHTML(@config.name_of('booktitle'))}</h1>\n)
436
447
  @body << %Q(<h2 class="tp-subtitle">#{CGI.escapeHTML(@config.name_of('subtitle'))}</h2>\n) if @config['subtitle']
437
448
  @body << %Q(<h2 class="tp-author">#{CGI.escapeHTML(@config.names_of('aut').join(ReVIEW::I18n.t('names_splitter')))}</h2>\n) if @config['aut']
438
- @body << %Q(<h3 class="tp-publisher">#{CGI.escapeHTML(@config.names_of('prt').join(ReVIEW::I18n.t('names_splitter')))}</h3>\n) if @config['prt']
449
+ @body << %Q(<h3 class="tp-publisher">#{CGI.escapeHTML(@config.names_of('pbl').join(ReVIEW::I18n.t('names_splitter')))}</h3>\n) if @config['pbl']
439
450
  @body << '</div>'
440
451
 
441
452
  @language = @producer.config['language']
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2008-2017 Minero Aoki, Kenshi Muto, Masayoshi Takahashi,
1
+ # Copyright (c) 2008-2018 Minero Aoki, Kenshi Muto, Masayoshi Takahashi,
2
2
  # KADO Masanori
3
3
  # 2002-2007 Minero Aoki
4
4
  #
@@ -20,7 +20,9 @@ module ReVIEW
20
20
  include TextUtils
21
21
  include HTMLUtils
22
22
 
23
- [:ref].each { |e| Compiler.definline(e) }
23
+ [:ref].each do |e|
24
+ Compiler.definline(e)
25
+ end
24
26
  Compiler.defblock(:planning, 0..1)
25
27
  Compiler.defblock(:best, 0..1)
26
28
  Compiler.defblock(:security, 0..1)
@@ -101,7 +103,9 @@ module ReVIEW
101
103
  @next_title = @next ? compile_inline(@next.title) : ''
102
104
  @prev_title = @prev ? compile_inline(@prev.title) : ''
103
105
 
104
- @toc = ReVIEW::WEBTOCPrinter.book_to_string(@book) if @book.config.maker == 'webmaker'
106
+ if @book.config.maker == 'webmaker'
107
+ @toc = ReVIEW::WEBTOCPrinter.book_to_string(@book)
108
+ end
105
109
 
106
110
  ReVIEW::Template.load(layoutfile).result(binding)
107
111
  end
@@ -116,10 +120,14 @@ module ReVIEW
116
120
 
117
121
  def headline(level, label, caption)
118
122
  prefix, anchor = headline_prefix(level)
119
- prefix = %Q(<span class="secno">#{prefix}</span>) if prefix
123
+ if prefix
124
+ prefix = %Q(<span class="secno">#{prefix}</span>)
125
+ end
120
126
  puts '' if level > 1
121
127
  a_id = ''
122
- a_id = %Q(<a id="h#{anchor}"></a>) if anchor
128
+ if anchor
129
+ a_id = %Q(<a id="h#{anchor}"></a>)
130
+ end
123
131
 
124
132
  if caption.empty?
125
133
  puts a_id if label
@@ -282,7 +290,9 @@ module ReVIEW
282
290
  puts %Q(<div class="syntax">)
283
291
  puts %Q(<p class="caption">#{compile_inline(caption)}</p>) if caption.present?
284
292
  print %Q(<pre class="syntax">)
285
- lines.each { |line| puts detab(line) }
293
+ lines.each do |line|
294
+ puts detab(line)
295
+ end
286
296
  puts '</pre>'
287
297
  puts '</div>'
288
298
  end
@@ -435,7 +445,9 @@ module ReVIEW
435
445
  class_names.push('highlight') if highlight?
436
446
  print %Q(<pre class="#{class_names.join(' ')}">)
437
447
  first_line_num = line_num
438
- lines.each_with_index { |line, i| puts detab((i + first_line_num).to_s.rjust(2) + ': ' + line) }
448
+ lines.each_with_index do |line, i|
449
+ puts detab((i + first_line_num).to_s.rjust(2) + ': ' + line)
450
+ end
439
451
  puts '</pre>'
440
452
  end
441
453
  end
@@ -470,7 +482,9 @@ module ReVIEW
470
482
  class_names.push('highlight') if highlight?
471
483
  print %Q(<pre class="#{class_names.join(' ')}">)
472
484
  first_line_num = line_num
473
- lines.each_with_index { |line, i| puts detab((i + first_line_num).to_s.rjust(2) + ': ' + line) }
485
+ lines.each_with_index do |line, i|
486
+ puts detab((i + first_line_num).to_s.rjust(2) + ': ' + line)
487
+ end
474
488
  puts '</pre>'
475
489
  end
476
490
 
@@ -490,7 +504,9 @@ module ReVIEW
490
504
 
491
505
  def quotedlist(lines, css_class)
492
506
  print %Q(<blockquote><pre class="#{css_class}">)
493
- lines.each { |line| puts detab(line) }
507
+ lines.each do |line|
508
+ puts detab(line)
509
+ end
494
510
  puts '</pre></blockquote>'
495
511
  end
496
512
  private :quotedlist
@@ -541,7 +557,9 @@ module ReVIEW
541
557
  end
542
558
 
543
559
  def handle_metric(str)
544
- return { 'class' => sprintf('width-%03dper', ($1.to_f * 100).round) } if str =~ /\Ascale=([\d.]+)\Z/
560
+ if str =~ /\Ascale=([\d.]+)\Z/
561
+ return { 'class' => sprintf('width-%03dper', ($1.to_f * 100).round) }
562
+ end
545
563
 
546
564
  k, v = str.split('=', 2)
547
565
  { k => v.sub(/\A["']/, '').sub(/["']\Z/, '') }
@@ -572,7 +590,9 @@ module ReVIEW
572
590
  warn "image not bound: #{id}"
573
591
  puts %Q(<div id="#{normalize_id(id)}" class="image">)
574
592
  puts %Q(<pre class="dummyimage">)
575
- lines.each { |line| puts detab(line) }
593
+ lines.each do |line|
594
+ puts detab(line)
595
+ end
576
596
  puts '</pre>'
577
597
  image_header id, caption
578
598
  puts '</div>'
@@ -615,8 +635,12 @@ module ReVIEW
615
635
  table_begin rows.first.size
616
636
  return if rows.empty?
617
637
  if sepidx
618
- sepidx.times { tr(rows.shift.map { |s| th(s) }) }
619
- rows.each { |cols| tr(cols.map { |s| td(s) }) }
638
+ sepidx.times do
639
+ tr(rows.shift.map { |s| th(s) })
640
+ end
641
+ rows.each do |cols|
642
+ tr(cols.map { |s| td(s) })
643
+ end
620
644
  else
621
645
  rows.each do |cols|
622
646
  h, *cs = *cols
@@ -711,7 +735,9 @@ module ReVIEW
711
735
  warn "image not bound: #{id}"
712
736
  if lines
713
737
  puts %Q(<pre class="dummyimage">)
714
- lines.each { |line| puts detab(line) }
738
+ lines.each do |line|
739
+ puts detab(line)
740
+ end
715
741
  puts '</pre>'
716
742
  end
717
743
  end
@@ -734,8 +760,8 @@ module ReVIEW
734
760
  puts %Q(<a id="#{normalize_id(id)}"></a>)
735
761
  end
736
762
 
737
- def linebreak
738
- puts '<br />'
763
+ def blankline
764
+ puts '<p><br /></p>'
739
765
  end
740
766
 
741
767
  def pagebreak
@@ -744,7 +770,9 @@ module ReVIEW
744
770
 
745
771
  def bpo(lines)
746
772
  puts '<bpo>'
747
- lines.each { |line| puts detab(line) }
773
+ lines.each do |line|
774
+ puts detab(line)
775
+ end
748
776
  puts '</bpo>'
749
777
  end
750
778
 
@@ -771,7 +799,6 @@ module ReVIEW
771
799
  end
772
800
  rescue KeyError
773
801
  error "unknown chapter: #{id}"
774
- nofunc_text("[UnknownChapter:#{id}]")
775
802
  end
776
803
 
777
804
  def inline_chap(id)
@@ -782,7 +809,6 @@ module ReVIEW
782
809
  end
783
810
  rescue KeyError
784
811
  error "unknown chapter: #{id}"
785
- nofunc_text("[UnknownChapter:#{id}]")
786
812
  end
787
813
 
788
814
  def inline_title(id)
@@ -794,7 +820,6 @@ module ReVIEW
794
820
  end
795
821
  rescue KeyError
796
822
  error "unknown chapter: #{id}"
797
- nofunc_text("[UnknownChapter:#{id}]")
798
823
  end
799
824
 
800
825
  def inline_fn(id)
@@ -803,6 +828,8 @@ module ReVIEW
803
828
  else
804
829
  %Q(<a id="fnb-#{normalize_id(id)}" href="#fn-#{normalize_id(id)}" class="noteref">*#{@chapter.footnote(id).number}</a>)
805
830
  end
831
+ rescue KeyError
832
+ error "unknown footnote: #{id}"
806
833
  end
807
834
 
808
835
  def compile_ruby(base, ruby)
@@ -921,6 +948,8 @@ module ReVIEW
921
948
 
922
949
  def inline_bib(id)
923
950
  %Q(<a href="#{@book.bib_file.gsub(/\.re\Z/, ".#{@book.config['htmlext']}")}#bib-#{normalize_id(id)}">[#{@chapter.bibpaper(id).number}]</a>)
951
+ rescue KeyError
952
+ error "unknown bib: #{id}"
924
953
  end
925
954
 
926
955
  def inline_hd_chap(chap, id)
@@ -936,6 +965,8 @@ module ReVIEW
936
965
  else
937
966
  str
938
967
  end
968
+ rescue KeyError
969
+ error "unknown headline: #{id}"
939
970
  end
940
971
 
941
972
  def column_label(id, chapter = @chapter)
@@ -950,6 +981,8 @@ module ReVIEW
950
981
  else
951
982
  I18n.t('column', compile_inline(chapter.column(id).caption))
952
983
  end
984
+ rescue KeyError
985
+ error "unknown column: #{id}"
953
986
  end
954
987
 
955
988
  def inline_list(id)
@@ -967,7 +1000,6 @@ module ReVIEW
967
1000
  end
968
1001
  rescue KeyError
969
1002
  error "unknown list: #{id}"
970
- nofunc_text("[UnknownList:#{id}]")
971
1003
  end
972
1004
 
973
1005
  def inline_table(id)
@@ -985,7 +1017,6 @@ module ReVIEW
985
1017
  end
986
1018
  rescue KeyError
987
1019
  error "unknown table: #{id}"
988
- nofunc_text("[UnknownTable:#{id}]")
989
1020
  end
990
1021
 
991
1022
  def inline_img(id)
@@ -1003,7 +1034,6 @@ module ReVIEW
1003
1034
  end
1004
1035
  rescue KeyError
1005
1036
  error "unknown image: #{id}"
1006
- nofunc_text("[UnknownImage:#{id}]")
1007
1037
  end
1008
1038
 
1009
1039
  def inline_asis(str, tag)
@@ -1110,7 +1140,9 @@ module ReVIEW
1110
1140
  def inline_tcy(str)
1111
1141
  # 縦中横用のtcy、uprightのCSSスタイルについては電書協ガイドラインを参照
1112
1142
  style = 'tcy'
1113
- style = 'upright' if str.size == 1 && str.match(/[[:ascii:]]/)
1143
+ if str.size == 1 && str.match(/[[:ascii:]]/)
1144
+ style = 'upright'
1145
+ end
1114
1146
  %Q(<span class="#{style}">#{escape_html(str)}</span>)
1115
1147
  end
1116
1148