review 3.2.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +26 -4
  3. data/.travis.yml +1 -1
  4. data/NEWS.ja.md +97 -1
  5. data/NEWS.md +97 -1
  6. data/bin/review-catalog-converter +1 -1
  7. data/bin/review-check +5 -5
  8. data/bin/review-checkdep +1 -1
  9. data/bin/review-compile +5 -5
  10. data/bin/review-idgxmlmaker +16 -0
  11. data/bin/review-index +7 -7
  12. data/bin/review-preproc +9 -9
  13. data/bin/review-validate +2 -2
  14. data/bin/review-vol +5 -5
  15. data/doc/config.yml.sample +14 -6
  16. data/doc/config.yml.sample-simple +1 -1
  17. data/doc/format.ja.md +15 -5
  18. data/doc/format.md +30 -18
  19. data/doc/pdfmaker.ja.md +1 -1
  20. data/doc/pdfmaker.md +1 -1
  21. data/lib/review/book.rb +1 -1
  22. data/lib/review/book/base.rb +23 -63
  23. data/lib/review/book/chapter.rb +18 -3
  24. data/lib/review/book/compilable.rb +5 -0
  25. data/lib/review/book/index.rb +26 -65
  26. data/lib/review/book/index/item.rb +40 -0
  27. data/lib/review/book/part.rb +22 -2
  28. data/lib/review/builder.rb +60 -40
  29. data/lib/review/catalog.rb +12 -15
  30. data/lib/review/compiler.rb +68 -36
  31. data/lib/review/configure.rb +10 -7
  32. data/lib/review/epubmaker.rb +5 -2
  33. data/lib/review/htmlbuilder.rb +24 -71
  34. data/lib/review/htmlutils.rb +2 -3
  35. data/lib/review/i18n.rb +2 -2
  36. data/lib/review/idgxmlbuilder.rb +101 -55
  37. data/lib/review/idgxmlmaker.rb +184 -0
  38. data/lib/review/init-web/finish.html +10 -0
  39. data/lib/review/init-web/index.html +190 -0
  40. data/lib/review/init-web/review-layout-design.js +691 -0
  41. data/lib/review/init.rb +110 -26
  42. data/lib/review/latexbuilder.rb +76 -54
  43. data/lib/review/lineinput.rb +1 -1
  44. data/lib/review/logger.rb +4 -8
  45. data/lib/review/makerhelper.rb +6 -4
  46. data/lib/review/markdownbuilder.rb +25 -38
  47. data/lib/review/md2inaobuilder.rb +3 -5
  48. data/lib/review/pdfmaker.rb +15 -15
  49. data/lib/review/plaintextbuilder.rb +67 -76
  50. data/lib/review/preprocessor.rb +13 -13
  51. data/lib/review/rstbuilder.rb +31 -31
  52. data/lib/review/textmaker.rb +13 -3
  53. data/lib/review/textutils.rb +77 -2
  54. data/lib/review/tocparser.rb +17 -17
  55. data/lib/review/tocprinter.rb +8 -8
  56. data/lib/review/topbuilder.rb +76 -57
  57. data/lib/review/update.rb +16 -16
  58. data/lib/review/version.rb +1 -1
  59. data/lib/review/webmaker.rb +2 -2
  60. data/lib/review/yamlloader.rb +3 -0
  61. data/review.gemspec +4 -3
  62. data/samples/sample-book/README.md +7 -2
  63. data/samples/sample-book/src/.gitignore +153 -0
  64. data/samples/sample-book/src/config-jlreq.yml +6 -0
  65. data/samples/sample-book/src/lib/tasks/review.rake +20 -9
  66. data/samples/sample-book/src/lib/tasks/z01_copy_sty.rake +14 -8
  67. data/samples/syntax-book/ch03.re +3 -6
  68. data/samples/syntax-book/config-jlreq.yml +5 -0
  69. data/samples/syntax-book/lib/tasks/review.rake +7 -7
  70. data/samples/syntax-book/lib/tasks/z01_copy_sty.rake +14 -8
  71. data/templates/latex/config.erb +6 -0
  72. data/templates/latex/layout.tex.erb +1 -0
  73. data/templates/latex/review-jlreq/review-base.sty +93 -31
  74. data/templates/latex/review-jlreq/review-jlreq.cls +6 -0
  75. data/templates/latex/review-jlreq/review-style.sty +3 -0
  76. data/templates/latex/review-jsbook/README.md +39 -0
  77. data/templates/latex/review-jsbook/review-base.sty +65 -10
  78. data/templates/latex/review-jsbook/review-jsbook.cls +4 -0
  79. data/templates/latex/review-jsbook/review-style.sty +4 -1
  80. data/test/assets/test_template.tex +11 -3
  81. data/test/assets/test_template_backmatter.tex +11 -3
  82. data/test/test_book.rb +65 -19
  83. data/test/test_catalog.rb +18 -42
  84. data/test/test_catalog_converter_cmd.rb +1 -1
  85. data/test/test_epubmaker_cmd.rb +2 -2
  86. data/test/test_helper.rb +1 -1
  87. data/test/test_htmlbuilder.rb +144 -55
  88. data/test/test_i18n.rb +25 -25
  89. data/test/test_idgxmlbuilder.rb +60 -18
  90. data/test/test_image_finder.rb +6 -6
  91. data/test/test_latexbuilder.rb +128 -24
  92. data/test/test_latexbuilder_v2.rb +23 -23
  93. data/test/test_logger.rb +14 -1
  94. data/test/test_makerhelper.rb +3 -3
  95. data/test/test_markdownbuilder.rb +45 -4
  96. data/test/test_md2inaobuilder.rb +12 -2
  97. data/test/test_pdfmaker.rb +1 -1
  98. data/test/test_pdfmaker_cmd.rb +1 -1
  99. data/test/test_plaintextbuilder.rb +31 -6
  100. data/test/test_rstbuilder.rb +33 -4
  101. data/test/test_textutils.rb +109 -2
  102. data/test/test_topbuilder.rb +35 -7
  103. data/test/test_update.rb +17 -8
  104. data/test/test_yamlloader.rb +13 -0
  105. metadata +26 -2
@@ -3,8 +3,8 @@ require 'yaml'
3
3
  module ReVIEW
4
4
  class Catalog
5
5
  def initialize(file)
6
- if file.respond_to? :read
7
- @yaml = YAML.load(file.read)
6
+ if file.respond_to?(:read)
7
+ @yaml = YAML.safe_load(file.read, [Date])
8
8
  else ## as Object
9
9
  @yaml = file
10
10
  end
@@ -12,12 +12,11 @@ module ReVIEW
12
12
  end
13
13
 
14
14
  def predef
15
- return '' unless @yaml['PREDEF']
16
- @yaml['PREDEF'].join("\n")
15
+ @yaml['PREDEF'] || []
17
16
  end
18
17
 
19
18
  def chaps
20
- return '' unless @yaml['CHAPS']
19
+ return [] unless @yaml['CHAPS']
21
20
 
22
21
  @yaml['CHAPS'].map do |entry|
23
22
  if entry.is_a?(String)
@@ -25,11 +24,11 @@ module ReVIEW
25
24
  elsif entry.is_a?(Hash)
26
25
  entry.values # chaps in a part
27
26
  end
28
- end.flatten.join("\n")
27
+ end.flatten
29
28
  end
30
29
 
31
30
  def parts
32
- return '' unless @yaml['CHAPS']
31
+ return [] unless @yaml['CHAPS']
33
32
 
34
33
  part_list = @yaml['CHAPS'].map do |entry|
35
34
  if entry.is_a?(Hash)
@@ -37,7 +36,7 @@ module ReVIEW
37
36
  end
38
37
  end
39
38
 
40
- part_list.flatten.compact.join("\n")
39
+ part_list.flatten.compact
41
40
  end
42
41
 
43
42
  def replace_part(old_name, new_name)
@@ -55,13 +54,11 @@ module ReVIEW
55
54
  end
56
55
 
57
56
  def appendix
58
- return '' unless @yaml['APPENDIX']
59
- @yaml['APPENDIX'].join("\n")
57
+ @yaml['APPENDIX'] || []
60
58
  end
61
59
 
62
60
  def postdef
63
- return '' unless @yaml['POSTDEF']
64
- @yaml['POSTDEF'].join("\n")
61
+ @yaml['POSTDEF'] || []
65
62
  end
66
63
 
67
64
  def to_s
@@ -71,7 +68,7 @@ module ReVIEW
71
68
  def validate!(config, basedir)
72
69
  filenames = []
73
70
  if predef.present?
74
- filenames.concat(predef.split(/\n/))
71
+ filenames.concat(predef)
75
72
  end
76
73
  parts_with_chaps.each do |chap|
77
74
  if chap.is_a?(Hash)
@@ -86,10 +83,10 @@ module ReVIEW
86
83
  end
87
84
  end
88
85
  if appendix.present?
89
- filenames.concat(appendix.split(/\n/))
86
+ filenames.concat(appendix)
90
87
  end
91
88
  if postdef.present?
92
- filenames.concat(postdef.split(/\n/))
89
+ filenames.concat(postdef)
93
90
  end
94
91
  filenames.each do |filename|
95
92
  refile = File.join(basedir, config['contentdir'], filename)
@@ -16,6 +16,12 @@ module ReVIEW
16
16
  class Compiler
17
17
  def initialize(strategy)
18
18
  @strategy = strategy
19
+
20
+ ## commands which do not parse block lines in compiler
21
+ @non_parsed_commands = %i[embed texequation graph]
22
+
23
+ ## to decide escaping/non-escaping for text
24
+ @command_name_stack = []
19
25
  end
20
26
 
21
27
  attr_reader :strategy
@@ -66,11 +72,11 @@ module ReVIEW
66
72
  SYNTAX = {}
67
73
 
68
74
  def self.defblock(name, argc, optional = false, &block)
69
- defsyntax name, (optional ? :optional : :block), argc, &block
75
+ defsyntax(name, (optional ? :optional : :block), argc, &block)
70
76
  end
71
77
 
72
78
  def self.defsingle(name, argc, &block)
73
- defsyntax name, :line, argc, &block
79
+ defsyntax(name, :line, argc, &block)
74
80
  end
75
81
 
76
82
  def self.defsyntax(name, type, argc, &block)
@@ -217,32 +223,47 @@ module ReVIEW
217
223
 
218
224
  def do_compile
219
225
  f = LineInput.new(StringIO.new(@chapter.content))
220
- @strategy.bind self, @chapter, Location.new(@chapter.basename, f)
226
+ @strategy.bind(self, @chapter, Location.new(@chapter.basename, f))
227
+
228
+ @non_parsed_commands = %i[embed texequation graph]
229
+ if @strategy.highlight?
230
+ @non_escaped_commands = %i[list emlist listnum emlistnum cmd]
231
+ else
232
+ @non_escaped_commands = []
233
+ end
234
+ @command_name_stack = []
235
+
221
236
  tagged_section_init
222
237
  while f.next?
223
238
  case f.peek
224
239
  when /\A\#@/
225
240
  f.gets # Nothing to do
226
241
  when /\A=+[\[\s\{]/
227
- compile_headline f.gets
242
+ compile_headline(f.gets)
228
243
  when /\A\s+\*/
229
- compile_ulist f
244
+ compile_ulist(f)
230
245
  when /\A\s+\d+\./
231
- compile_olist f
246
+ compile_olist(f)
247
+ when /\A\s+:\s/
248
+ compile_dlist(f)
232
249
  when /\A\s*:\s/
233
- compile_dlist f
250
+ warn 'Definition list starting with `:` is deprecated. It should start with ` : `.'
251
+ compile_dlist(f)
234
252
  when %r{\A//\}}
235
253
  f.gets
236
254
  error 'block end seen but not opened'
237
255
  when %r{\A//[a-z]+}
256
+ # @command_name_stack.push(name) ## <- move into read_command() to use name
238
257
  name, args, lines = read_command(f)
239
258
  syntax = syntax_descriptor(name)
240
259
  unless syntax
241
260
  error "unknown command: //#{name}"
242
- compile_unknown_command args, lines
261
+ compile_unknown_command(args, lines)
262
+ @command_name_stack.pop
243
263
  next
244
264
  end
245
- compile_command syntax, args, lines
265
+ compile_command(syntax, args, lines)
266
+ @command_name_stack.pop
246
267
  when %r{\A//}
247
268
  line = f.gets
248
269
  warn "`//' seen but is not valid command: #{line.strip.inspect}"
@@ -255,7 +276,7 @@ module ReVIEW
255
276
  f.gets
256
277
  next
257
278
  end
258
- compile_paragraph f
279
+ compile_paragraph(f)
259
280
  end
260
281
  end
261
282
  close_all_tagged_section
@@ -296,7 +317,7 @@ module ReVIEW
296
317
  end
297
318
  @headline_indexs[index] += 1
298
319
  close_current_tagged_section(level)
299
- @strategy.headline level, label, caption
320
+ @strategy.headline(level, label, caption)
300
321
  end
301
322
  end
302
323
 
@@ -307,7 +328,7 @@ module ReVIEW
307
328
  end
308
329
 
309
330
  def headline(level, label, caption)
310
- @strategy.headline level, label, caption
331
+ @strategy.headline(level, label, caption)
311
332
  end
312
333
 
313
334
  def tagged_section_init
@@ -318,17 +339,17 @@ module ReVIEW
318
339
  mid = "#{tag}_begin"
319
340
  unless @strategy.respond_to?(mid)
320
341
  error "strategy does not support tagged section: #{tag}"
321
- headline level, label, caption
342
+ headline(level, label, caption)
322
343
  return
323
344
  end
324
- @tagged_section.push [tag, level]
325
- @strategy.__send__ mid, level, label, caption
345
+ @tagged_section.push([tag, level])
346
+ @strategy.__send__(mid, level, label, caption)
326
347
  end
327
348
 
328
349
  def close_tagged_section(tag, level)
329
350
  mid = "#{tag}_end"
330
351
  if @strategy.respond_to?(mid)
331
- @strategy.__send__ mid, level
352
+ @strategy.__send__(mid, level)
332
353
  else
333
354
  error "strategy does not support block op: #{mid}"
334
355
  end
@@ -347,7 +368,7 @@ module ReVIEW
347
368
 
348
369
  buf = [text(line.sub(/\*+/, '').strip)]
349
370
  f.while_match(/\A\s+(?!\*)\S/) do |cont|
350
- buf.push text(cont.strip)
371
+ buf.push(text(cont.strip))
351
372
  end
352
373
 
353
374
  line =~ /\A\s+(\*+)/
@@ -355,7 +376,7 @@ module ReVIEW
355
376
  if level == current_level
356
377
  @strategy.ul_item_end
357
378
  # body
358
- @strategy.ul_item_begin buf
379
+ @strategy.ul_item_begin(buf)
359
380
  elsif level < current_level # down
360
381
  level_diff = current_level - level
361
382
  if level_diff != 1
@@ -363,7 +384,7 @@ module ReVIEW
363
384
  end
364
385
  level = current_level
365
386
  @strategy.ul_begin { level }
366
- @strategy.ul_item_begin buf
387
+ @strategy.ul_item_begin(buf)
367
388
  elsif level > current_level # up
368
389
  level_diff = level - current_level
369
390
  level = current_level
@@ -373,7 +394,7 @@ module ReVIEW
373
394
  end
374
395
  @strategy.ul_item_end
375
396
  # body
376
- @strategy.ul_item_begin buf
397
+ @strategy.ul_item_begin(buf)
377
398
  end
378
399
  end
379
400
 
@@ -391,9 +412,9 @@ module ReVIEW
391
412
  num = line.match(/(\d+)\./)[1]
392
413
  buf = [text(line.sub(/\d+\./, '').strip)]
393
414
  f.while_match(/\A\s+(?!\d+\.)\S/) do |cont|
394
- buf.push text(cont.strip)
415
+ buf.push(text(cont.strip))
395
416
  end
396
- @strategy.ol_item buf, num
417
+ @strategy.ol_item(buf, num)
397
418
  end
398
419
  @strategy.ol_end
399
420
  end
@@ -401,7 +422,7 @@ module ReVIEW
401
422
  def compile_dlist(f)
402
423
  @strategy.dl_begin
403
424
  while /\A\s*:/ =~ f.peek
404
- @strategy.dt text(f.gets.sub(/\A\s*:/, '').strip)
425
+ @strategy.dt(text(f.gets.sub(/\A\s*:/, '').strip))
405
426
  desc = f.break(/\A(\S|\s*:|\s+\d+\.\s|\s+\*\s)/).map { |line| text(line.strip) }
406
427
  @strategy.dd(desc)
407
428
  f.skip_blank_lines
@@ -414,15 +435,16 @@ module ReVIEW
414
435
  buf = []
415
436
  f.until_match(%r{\A//|\A\#@}) do |line|
416
437
  break if line.strip.empty?
417
- buf.push text(line.sub(/^(\t+)\s*/) { |m| '<!ESCAPETAB!>' * m.size }.strip.gsub('<!ESCAPETAB!>', "\t"))
438
+ buf.push(text(line.sub(/^(\t+)\s*/) { |m| '<!ESCAPETAB!>' * m.size }.strip.gsub('<!ESCAPETAB!>', "\t")))
418
439
  end
419
- @strategy.paragraph buf
440
+ @strategy.paragraph(buf)
420
441
  end
421
442
 
422
443
  def read_command(f)
423
444
  line = f.gets
424
445
  name = line.slice(/[a-z]+/).to_sym
425
- ignore_inline = (name == :embed)
446
+ ignore_inline = @non_parsed_commands.include?(name)
447
+ @command_name_stack.push(name)
426
448
  args = parse_args(line.sub(%r{\A//[a-z]+}, '').rstrip.chomp('{'), name)
427
449
  @strategy.doc_status[name] = true
428
450
  lines = block_open?(line) ? read_block(f, ignore_inline) : nil
@@ -439,9 +461,9 @@ module ReVIEW
439
461
  buf = []
440
462
  f.until_match(%r{\A//\}}) do |line|
441
463
  if ignore_inline
442
- buf.push line
464
+ buf.push(line.chomp)
443
465
  elsif line !~ /\A\#@/
444
- buf.push text(line.rstrip)
466
+ buf.push(text(line.rstrip, true))
445
467
  end
446
468
  end
447
469
  unless %r{\A//\}} =~ f.peek
@@ -473,27 +495,27 @@ module ReVIEW
473
495
  def compile_command(syntax, args, lines)
474
496
  unless @strategy.respond_to?(syntax.name)
475
497
  error "strategy does not support command: //#{syntax.name}"
476
- compile_unknown_command args, lines
498
+ compile_unknown_command(args, lines)
477
499
  return
478
500
  end
479
501
  begin
480
- syntax.check_args args
502
+ syntax.check_args(args)
481
503
  rescue CompileError => e
482
504
  error e.message
483
505
  args = ['(NoArgument)'] * syntax.min_argc
484
506
  end
485
507
  if syntax.block_allowed?
486
- compile_block syntax, args, lines
508
+ compile_block(syntax, args, lines)
487
509
  else
488
510
  if lines
489
511
  error "block is not allowed for command //#{syntax.name}; ignore"
490
512
  end
491
- compile_single syntax, args
513
+ compile_single(syntax, args)
492
514
  end
493
515
  end
494
516
 
495
517
  def compile_unknown_command(args, lines)
496
- @strategy.unknown_command args, lines
518
+ @strategy.unknown_command(args, lines)
497
519
  end
498
520
 
499
521
  def compile_block(syntax, args, lines)
@@ -527,7 +549,12 @@ module ReVIEW
527
549
  str.gsub("\x01", '@').gsub("\x02", '\\').gsub("\x03", '{').gsub("\x04", '}')
528
550
  end
529
551
 
530
- def text(str)
552
+ def in_non_escaped_command?
553
+ current_command = @command_name_stack.last
554
+ current_command && @non_escaped_commands.include?(current_command)
555
+ end
556
+
557
+ def text(str, block_mode = false)
531
558
  return '' if str.empty?
532
559
  words = replace_fence(str).split(/(@<\w+>\{(?:[^\}\\]|\\.)*?\})/, -1)
533
560
  words.each do |w|
@@ -535,10 +562,15 @@ module ReVIEW
535
562
  error "`@<xxx>' seen but is not valid inline op: #{w}"
536
563
  end
537
564
  end
538
- result = @strategy.nofunc_text(revert_replace_fence(words.shift))
565
+ result = ''
539
566
  until words.empty?
567
+ if in_non_escaped_command? && block_mode
568
+ result << revert_replace_fence(words.shift)
569
+ else
570
+ result << @strategy.nofunc_text(revert_replace_fence(words.shift))
571
+ end
572
+ break if words.empty?
540
573
  result << compile_inline(revert_replace_fence(words.shift.gsub(/\\\}/, '}').gsub(/\\\\/, '\\')))
541
- result << @strategy.nofunc_text(revert_replace_fence(words.shift))
542
574
  end
543
575
  result
544
576
  rescue => e
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2012-2018 Masanori Kado, Masayoshi Takahashi, Kenshi Muto
2
+ # Copyright (c) 2012-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
@@ -15,10 +15,10 @@ module ReVIEW
15
15
  def self.values
16
16
  conf = Configure[
17
17
  # These parameters can be overridden by YAML file.
18
- 'bookname' => 'example', # it defines epub file name also
18
+ 'bookname' => 'book', # it defines epub file name also
19
19
  'booktitle' => 'Re:VIEW Sample Book',
20
20
  'title' => nil,
21
- 'aut' => nil, # author
21
+ 'aut' => ['anonymous'], # author
22
22
  'prt' => nil, # printer(publisher)
23
23
  'asn' => nil, # associated name
24
24
  'ant' => nil, # bibliographic antecedent
@@ -32,7 +32,7 @@ module ReVIEW
32
32
  'rights' => nil, # Copyright messages
33
33
  'description' => nil, # Description
34
34
  'urnid' => "urn:uid:#{SecureRandom.uuid}", # Identifier
35
- 'stylesheet' => 'stylesheet.css', # stylesheet file
35
+ 'stylesheet' => [], # stylesheet file
36
36
  'coverfile' => nil, # content file of body of cover page
37
37
  'mytoc' => nil, # whether make own table of contents or not
38
38
  'params' => '', # specify review2html parameters
@@ -65,6 +65,7 @@ module ReVIEW
65
65
  'words_file' => nil,
66
66
  'colophon_order' => %w[aut csl trl dsr ill cov edt pbl contact prt],
67
67
  'externallink' => true,
68
+ 'join_lines_by_lang' => nil, # experimental. default should be nil
68
69
  # for IDGXML
69
70
  'tableopt' => nil,
70
71
  'listinfo' => nil,
@@ -76,8 +77,9 @@ module ReVIEW
76
77
  'image_scale2width' => true,
77
78
  'footnotetext' => nil,
78
79
  'texcommand' => 'uplatex',
79
- 'texoptions' => '-interaction=nonstopmode -file-line-error',
80
+ 'texoptions' => '-interaction=nonstopmode -file-line-error -halt-on-error',
80
81
  '_texdocumentclass' => ['review-jsbook', ''],
82
+ 'texstyle' => ['reviewmacro'],
81
83
  'dvicommand' => 'dvipdfmx',
82
84
  'dvioptions' => '-d 5 -z 9',
83
85
  # for PDFMaker
@@ -88,7 +90,8 @@ module ReVIEW
88
90
  'makeindex_sty' => nil,
89
91
  'makeindex_dic' => nil,
90
92
  'makeindex_mecab' => true,
91
- 'makeindex_mecab_opts' => '-Oyomi'
93
+ 'makeindex_mecab_opts' => '-Oyomi',
94
+ 'use_cover_nombre' => true
92
95
  },
93
96
  'imgmath_options' => {
94
97
  'format' => 'png',
@@ -99,7 +102,7 @@ module ReVIEW
99
102
  'preamble_file' => nil,
100
103
  'fontsize' => 10,
101
104
  'lineheight' => 10 * 1.2,
102
- 'pdfcrop_pixelize_cmd' => 'pdftocairo -png -r 90 -f %p -l %p -singlefile %i %O',
105
+ 'pdfcrop_pixelize_cmd' => 'pdftocairo -%t -r 90 -f %p -l %p -singlefile %i %O',
103
106
  'dvipng_cmd' => 'dvipng -T tight -z 9 -p %p -l %p -o %o %i'
104
107
  }
105
108
  ]
@@ -39,12 +39,12 @@ module ReVIEW
39
39
  end
40
40
 
41
41
  def error(msg)
42
- @logger.error "#{File.basename($PROGRAM_NAME, '.*')}: #{msg}"
42
+ @logger.error msg
43
43
  exit 1
44
44
  end
45
45
 
46
46
  def warn(msg)
47
- @logger.warn "#{File.basename($PROGRAM_NAME, '.*')}: #{msg}"
47
+ @logger.warn msg
48
48
  end
49
49
 
50
50
  def log(msg)
@@ -500,6 +500,9 @@ module ReVIEW
500
500
  def copy_stylesheet(basetmpdir)
501
501
  return if @config['stylesheet'].empty?
502
502
  @config['stylesheet'].each do |sfile|
503
+ unless File.exist?(sfile)
504
+ error "#{sfile} is not found."
505
+ end
503
506
  FileUtils.cp(sfile, basetmpdir)
504
507
  @producer.contents.push(Content.new('file' => sfile))
505
508
  end