review 3.0.0.preview3 → 3.0.0.preview4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS.ja.md +26 -0
  3. data/NEWS.md +26 -0
  4. data/bin/review +2 -0
  5. data/bin/review-update +19 -0
  6. data/doc/format.ja.md +11 -0
  7. data/doc/format.md +11 -1
  8. data/doc/format_idg.ja.md +2 -4
  9. data/lib/review/book/chapter.rb +1 -0
  10. data/lib/review/book/compilable.rb +9 -0
  11. data/lib/review/book/index.rb +7 -1
  12. data/lib/review/builder.rb +29 -3
  13. data/lib/review/compiler.rb +2 -1
  14. data/lib/review/htmlbuilder.rb +40 -28
  15. data/lib/review/i18n.rb +8 -0
  16. data/lib/review/i18n.yml +22 -1
  17. data/lib/review/idgxmlbuilder.rb +42 -36
  18. data/lib/review/init.rb +2 -2
  19. data/lib/review/latexbuilder.rb +27 -1
  20. data/lib/review/makerhelper.rb +2 -1
  21. data/lib/review/plaintextbuilder.rb +27 -41
  22. data/lib/review/rstbuilder.rb +9 -1
  23. data/lib/review/topbuilder.rb +9 -1
  24. data/lib/review/update.rb +527 -0
  25. data/lib/review/version.rb +1 -1
  26. data/review.gemspec +1 -1
  27. data/samples/sample-book/README.md +1 -1
  28. data/samples/sample-book/src/Rakefile +2 -112
  29. data/samples/sample-book/src/config.yml +3 -1
  30. data/samples/sample-book/src/lib/tasks/review.rake +113 -0
  31. data/samples/sample-book/src/lib/tasks/z01_copy_sty.rake +17 -0
  32. data/samples/sample-book/src/sty/reviewmacro.sty +15 -1
  33. data/samples/syntax-book/Rakefile +2 -87
  34. data/samples/syntax-book/ch02.re +6 -1
  35. data/samples/syntax-book/config.yml +7 -4
  36. data/samples/syntax-book/images/cover-b5.ai +5735 -15
  37. data/samples/syntax-book/lib/tasks/review.rake +113 -0
  38. data/samples/syntax-book/lib/tasks/z01_copy_sty.rake +17 -0
  39. data/samples/syntax-book/sty/reviewmacro.sty +11 -35
  40. data/templates/latex/config.erb +1 -0
  41. data/templates/latex/review-jlreq/review-base.sty +4 -0
  42. data/templates/latex/review-jlreq/review-jlreq.cls +56 -2
  43. data/templates/latex/review-jlreq/review-style.sty +0 -6
  44. data/templates/latex/review-jsbook/review-base.sty +5 -0
  45. data/test/assets/test_template.tex +2 -1
  46. data/test/assets/test_template_backmatter.tex +2 -1
  47. data/test/test_htmlbuilder.rb +39 -1
  48. data/test/test_idgxmlbuilder.rb +24 -0
  49. data/test/test_latexbuilder.rb +39 -0
  50. data/test/test_pdfmaker_cmd.rb +1 -1
  51. data/test/test_plaintextbuilder.rb +19 -0
  52. data/test/test_topbuilder.rb +21 -0
  53. data/test/test_update.rb +450 -0
  54. metadata +12 -2
@@ -264,14 +264,7 @@ module ReVIEW
264
264
  end
265
265
 
266
266
  def inline_list(id)
267
- chapter, id = extract_chapter_id(id)
268
- if get_chap(chapter).nil?
269
- "<span type='list'>#{I18n.t('list')}#{I18n.t('format_number_without_chapter', [chapter.list(id).number])}</span>"
270
- else
271
- "<span type='list'>#{I18n.t('list')}#{I18n.t('format_number', [get_chap(chapter), chapter.list(id).number])}</span>"
272
- end
273
- rescue KeyError
274
- error "unknown list: #{id}"
267
+ "<span type='list'>#{super(id)}</span>"
275
268
  end
276
269
 
277
270
  def list_header(id, caption, _lang)
@@ -369,25 +362,15 @@ module ReVIEW
369
362
  end
370
363
 
371
364
  def inline_table(id)
372
- chapter, id = extract_chapter_id(id)
373
- if get_chap(chapter).nil?
374
- "<span type='table'>#{I18n.t('table')}#{I18n.t('format_number_without_chapter', [chapter.table(id).number])}</span>"
375
- else
376
- "<span type='table'>#{I18n.t('table')}#{I18n.t('format_number', [get_chap(chapter), chapter.table(id).number])}</span>"
377
- end
378
- rescue KeyError
379
- error "unknown table: #{id}"
365
+ "<span type='table'>#{super(id)}</span>"
380
366
  end
381
367
 
382
368
  def inline_img(id)
383
- chapter, id = extract_chapter_id(id)
384
- if get_chap(chapter).nil?
385
- "<span type='image'>#{I18n.t('image')}#{I18n.t('format_number_without_chapter', [chapter.image(id).number])}</span>"
386
- else
387
- "<span type='image'>#{I18n.t('image')}#{I18n.t('format_number', [get_chap(chapter), chapter.image(id).number])}</span>"
388
- end
389
- rescue KeyError
390
- error "unknown image: #{id}"
369
+ "<span type='image'>#{super(id)}</span>"
370
+ end
371
+
372
+ def inline_eq(id)
373
+ "<span type='eq'>#{super(id)}</span>"
391
374
  end
392
375
 
393
376
  def inline_imgref(id)
@@ -440,13 +423,26 @@ module ReVIEW
440
423
  end
441
424
  end
442
425
 
443
- def texequation(lines)
426
+ def texequation(lines, id = nil, caption = '')
444
427
  @texblockequation += 1
428
+ if id
429
+ puts '<equationblock>'
430
+ if get_chap.nil?
431
+ puts %Q(<caption>#{I18n.t('equation')}#{I18n.t('format_number_without_chapter', [@chapter.equation(id).number])}#{I18n.t('caption_prefix_idgxml')}#{compile_inline(caption)}</caption>)
432
+ else
433
+ puts %Q(<caption>#{I18n.t('equation')}#{I18n.t('format_number', [get_chap, @chapter.equation(id).number])}#{I18n.t('caption_prefix_idgxml')}#{compile_inline(caption)}</caption>)
434
+ end
435
+ end
436
+
445
437
  puts %Q(<replace idref="texblock-#{@texblockequation}">)
446
438
  puts '<pre>'
447
439
  puts lines.join("\n")
448
440
  puts '</pre>'
449
441
  puts '</replace>'
442
+
443
+ if id
444
+ puts '</equationblock>'
445
+ end
450
446
  end
451
447
 
452
448
  def table(lines, id = nil, caption = nil)
@@ -1067,20 +1063,30 @@ module ReVIEW
1067
1063
  end
1068
1064
 
1069
1065
  def inline_chapref(id)
1070
- chs = ['', '「', '」']
1071
- if @book.config['chapref']
1072
- chs2 = @book.config['chapref'].split(',')
1073
- if chs2.size != 3
1074
- error '--chapsplitter must have exactly 3 parameters with comma.'
1066
+ if @book.config.check_version('2', exception: false)
1067
+ # backward compatibility
1068
+ chs = ['', '「', '」']
1069
+ if @book.config['chapref']
1070
+ chs2 = @book.config['chapref'].split(',')
1071
+ if chs2.size != 3
1072
+ error '--chapsplitter must have exactly 3 parameters with comma.'
1073
+ else
1074
+ chs = chs2
1075
+ end
1076
+ end
1077
+ s = "#{chs[0]}#{@book.chapter_index.number(id)}#{chs[1]}#{@book.chapter_index.title(id)}#{chs[2]}"
1078
+ if @book.config['chapterlink']
1079
+ %Q(<link href="#{id}">#{s}</link>)
1075
1080
  else
1076
- chs = chs2
1081
+ s
1077
1082
  end
1078
- end
1079
- s = "#{chs[0]}#{@book.chapter_index.number(id)}#{chs[1]}#{@book.chapter_index.title(id)}#{chs[2]}"
1080
- if @book.config['chapterlink']
1081
- %Q(<link href="#{id}">#{s}</link>)
1082
1083
  else
1083
- s
1084
+ title = super
1085
+ if @book.config['chapterlink']
1086
+ %Q(<link href="#{id}">#{title}</link>)
1087
+ else
1088
+ title
1089
+ end
1084
1090
  end
1085
1091
  rescue KeyError
1086
1092
  error "unknown chapter: #{id}"
@@ -170,13 +170,13 @@ EOS
170
170
 
171
171
  File.open(dir + '/Rakefile', 'w') do |file|
172
172
  file.write <<-EOS
173
- Dir.glob('lib/tasks/*.rake').each do |file|
173
+ Dir.glob('lib/tasks/*.rake').sort.each do |file|
174
174
  load(file)
175
175
  end
176
176
  EOS
177
177
  end
178
178
 
179
- FileUtils.cp(@review_dir + '/samples/sample-book/src/Rakefile',
179
+ FileUtils.cp(@review_dir + '/samples/sample-book/src/lib/tasks/review.rake',
180
180
  dir + '/lib/tasks/review.rake')
181
181
  end
182
182
 
@@ -733,13 +733,28 @@ module ReVIEW
733
733
  latex_block 'flushright', lines
734
734
  end
735
735
 
736
- def texequation(lines)
736
+ def texequation(lines, id = nil, caption = '')
737
737
  blank
738
+
739
+ if id
740
+ puts macro('begin', 'reviewequationblock')
741
+ if get_chap.nil?
742
+ puts macro('reviewequationcaption', "#{I18n.t('equation')}#{I18n.t('format_number_header_without_chapter', [@chapter.equation(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
743
+ else
744
+ puts macro('reviewequationcaption', "#{I18n.t('equation')}#{I18n.t('format_number_header', [get_chap, @chapter.equation(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
745
+ end
746
+ end
747
+
738
748
  puts macro('begin', 'equation*')
739
749
  lines.each do |line|
740
750
  puts unescape(line)
741
751
  end
742
752
  puts macro('end', 'equation*')
753
+
754
+ if id
755
+ puts macro('end', 'reviewequationblock')
756
+ end
757
+
743
758
  blank
744
759
  end
745
760
 
@@ -863,6 +878,17 @@ module ReVIEW
863
878
  error "unknown image: #{id}"
864
879
  end
865
880
 
881
+ def inline_eq(id)
882
+ chapter, id = extract_chapter_id(id)
883
+ if get_chap(chapter).nil?
884
+ macro('reviewequationref', I18n.t('format_number_without_chapter', [chapter.equation(id).number]))
885
+ else
886
+ macro('reviewequationref', I18n.t('format_number', [get_chap(chapter), chapter.equation(id).number]))
887
+ end
888
+ rescue KeyError
889
+ error "unknown equation: #{id}"
890
+ end
891
+
866
892
  def footnote(id, content)
867
893
  if @book.config['footnotetext'] || @foottext[id]
868
894
  puts macro("footnotetext[#{@chapter.footnote(id).number}]", compile_inline(content.strip))
@@ -75,7 +75,7 @@ module ReVIEW
75
75
 
76
76
  def default_imgmath_preamble
77
77
  <<-EOB
78
- \\documentclass[uplatex]{jsarticle}
78
+ \\documentclass[uplatex,a3paper,landscape]{jsarticle}
79
79
  \\usepackage[deluxe,uplatex]{otf}
80
80
  \\usepackage[T1]{fontenc}
81
81
  \\usepackage{textcomp}
@@ -92,6 +92,7 @@ module ReVIEW
92
92
  \\usepackage{anyfontsize}
93
93
  \\usepackage{bm}
94
94
  \\pagestyle{empty}
95
+ % \\setpaperwidth{1000mm}
95
96
  EOB
96
97
  end
97
98
 
@@ -137,17 +137,6 @@ module ReVIEW
137
137
 
138
138
  alias_method :lead, :read
139
139
 
140
- def inline_list(id)
141
- chapter, id = extract_chapter_id(id)
142
- if get_chap(chapter)
143
- %Q(#{I18n.t('list')}#{I18n.t('format_number', [get_chap(chapter), chapter.list(id).number])})
144
- else
145
- %Q(#{I18n.t('list')}#{I18n.t('format_number_without_chapter', [chapter.list(id).number])})
146
- end
147
- rescue KeyError
148
- error "unknown list: #{id}"
149
- end
150
-
151
140
  def list_header(id, caption, _lang)
152
141
  blank
153
142
  if get_chap
@@ -207,28 +196,6 @@ module ReVIEW
207
196
  base_parablock 'quote', lines, nil
208
197
  end
209
198
 
210
- def inline_table(id)
211
- chapter, id = extract_chapter_id(id)
212
- if get_chap(chapter)
213
- "#{I18n.t('table')}#{I18n.t('format_number', [get_chap(chapter), chapter.table(id).number])}"
214
- else
215
- "#{I18n.t('table')}#{I18n.t('format_number_without_chapter', [chapter.table(id).number])}"
216
- end
217
- rescue KeyError
218
- error "unknown table: #{id}"
219
- end
220
-
221
- def inline_img(id)
222
- chapter, id = extract_chapter_id(id)
223
- if get_chap(chapter)
224
- "#{I18n.t('image')}#{I18n.t('format_number', [get_chap(chapter), chapter.image(id).number])}"
225
- else
226
- "#{I18n.t('image')}#{I18n.t('format_number_without_chapter', [chapter.image(id).number])}"
227
- end
228
- rescue KeyError
229
- error "unknown image: #{id}"
230
- end
231
-
232
199
  def image(_lines, id, caption, _metric = nil)
233
200
  blank
234
201
  if get_chap
@@ -239,7 +206,16 @@ module ReVIEW
239
206
  blank
240
207
  end
241
208
 
242
- def texequation(lines)
209
+ def texequation(lines, id = nil, caption = '')
210
+ if id
211
+ blank
212
+ if get_chap
213
+ puts "#{I18n.t('equation')}#{I18n.t('format_number', [get_chap, @chapter.equation(id).number])}#{I18n.t('caption_prefix_idgxml')}#{compile_inline(caption)}"
214
+ else
215
+ puts "#{I18n.t('equation')}#{I18n.t('format_number_without_chapter', [@chapter.equation(id).number])}#{I18n.t('caption_prefix_idgxml')}#{compile_inline(caption)}"
216
+ end
217
+ end
218
+
243
219
  puts lines.join("\n")
244
220
  blank
245
221
  end
@@ -623,15 +599,25 @@ module ReVIEW
623
599
  end
624
600
 
625
601
  def inline_chapref(id)
626
- chs = ['', '「', '」']
627
- if @book.config['chapref']
628
- chs2 = @book.config['chapref'].split(',')
629
- if chs2.size != 3
630
- error '--chapsplitter must have exactly 3 parameters with comma.'
602
+ if @book.config.check_version('2', exception: false)
603
+ # backward compatibility
604
+ chs = ['', '「', '」']
605
+ if @book.config['chapref']
606
+ chs2 = @book.config['chapref'].split(',')
607
+ if chs2.size != 3
608
+ error '--chapsplitter must have exactly 3 parameters with comma.'
609
+ end
610
+ chs = chs2
611
+ end
612
+ "#{chs[0]}#{@book.chapter_index.number(id)}#{chs[1]}#{@book.chapter_index.title(id)}#{chs[2]}"
613
+ else
614
+ title = super
615
+ if @book.config['chapterlink']
616
+ %Q(<link href="#{id}">#{title}</link>)
617
+ else
618
+ title
631
619
  end
632
- chs = chs2
633
620
  end
634
- "#{chs[0]}#{@book.chapter_index.number(id)}#{chs[1]}#{@book.chapter_index.title(id)}#{chs[2]}"
635
621
  rescue KeyError
636
622
  error "unknown chapter: #{id}"
637
623
  end
@@ -297,11 +297,19 @@ module ReVIEW
297
297
  blank
298
298
  end
299
299
 
300
- def texequation(lines)
300
+ def texequation(lines, id = nil, caption = '')
301
+ if id
302
+ puts ".. _#{id}:"
303
+ end
304
+
301
305
  puts '.. math::'
302
306
  blank
303
307
  puts lines.map { |line| " #{line}" }.join
304
308
  blank
309
+ if caption.present?
310
+ puts " #{caption}"
311
+ blank
312
+ end
305
313
  end
306
314
 
307
315
  def table_header(id, caption)
@@ -170,8 +170,16 @@ module ReVIEW
170
170
  blank
171
171
  end
172
172
 
173
- def texequation(lines)
173
+ def texequation(lines, id = nil, caption = '')
174
+ blank
174
175
  puts "◆→開始:#{@titles['texequation']}←◆"
176
+ if id
177
+ if get_chap
178
+ puts "#{I18n.t('equation')}#{I18n.t('format_number', [get_chap, @chapter.equation(id).number])}#{I18n.t('caption_prefix_idgxml')}#{compile_inline(caption)}"
179
+ else
180
+ puts "#{I18n.t('equation')}#{I18n.t('format_number_without_chapter', [@chapter.equation(id).number])}#{I18n.t('caption_prefix_idgxml')}#{compile_inline(caption)}"
181
+ end
182
+ end
175
183
  puts lines.join("\n")
176
184
  puts "◆→終了:#{@titles['texequation']}←◆"
177
185
  blank
@@ -0,0 +1,527 @@
1
+ #
2
+ # Copyright (c) 2018 Kenshi Muto
3
+ #
4
+ # This program is free software.
5
+ # You can distribute or modify this program under the terms of
6
+ # the GNU LGPL, Lesser General Public License version 2.1.
7
+ # For details of the GNU LGPL, see the file "COPYING".
8
+
9
+ require 'fileutils'
10
+ require 'optparse'
11
+ require 'review'
12
+ require 'review/i18n'
13
+ require 'yaml'
14
+ require 'digest'
15
+
16
+ module ReVIEW
17
+ class Update
18
+ def self.execute(*args)
19
+ new.execute(*args)
20
+ end
21
+
22
+ # should be
23
+ TARGET_VERSION = '3.0'
24
+ EPUB_VERSION = '3'
25
+ HTML_VERSION = '5'
26
+ TEX_DOCUMENTCLASS = ['review-jsbook', 'review-jlreq']
27
+ TEX_DOCUMENTCLASS_BAD = ['jsbook', nil]
28
+ TEX_DOCUMENTCLASS_OPTS = 'cameraready=print,paper=a5'
29
+ TEX_COMMAND = 'uplatex'
30
+ TEX_OPTIONS = '-interaction=nonstopmode -file-line-error'
31
+ DVI_COMMAND = 'dvipdfmx'
32
+ DVI_OPTIONS = '-d 5 -z 9'
33
+
34
+ attr_reader :config_ymls, :locale_ymls, :catalog_ymls, :tex_ymls, :epub_ymls
35
+ attr_accessor :force, :specified_template
36
+
37
+ def initialize
38
+ @template = nil
39
+ @specified_template = nil
40
+ @force = nil
41
+ @logger = ReVIEW.logger
42
+ @review_dir = File.dirname(File.expand_path('..', __dir__))
43
+ @config_ymls = []
44
+ @locale_ymls = []
45
+ @catalog_ymls = []
46
+ @tex_ymls = []
47
+ @epub_ymls = []
48
+
49
+ @backup = true
50
+ end
51
+
52
+ def execute(*args)
53
+ parse_options(args)
54
+ dir = Dir.pwd
55
+
56
+ parse_ymls(dir)
57
+ check_old_catalogs(dir)
58
+
59
+ show_version
60
+
61
+ if @config_ymls.empty?
62
+ @logger.error t("!! No *.yml file with 'review_version' was found. Aborted. !!")
63
+ raise ApplicationError
64
+ end
65
+
66
+ check_own_files(dir)
67
+ update_version
68
+ update_rakefile(dir)
69
+ update_epub_version
70
+ update_locale
71
+ update_tex_parameters
72
+ if @template
73
+ update_tex_stys(@template, dir)
74
+ end
75
+ update_tex_command
76
+ update_dvi_command
77
+
78
+ puts t('Finished.')
79
+ rescue ApplicationError
80
+ exit 1
81
+ end
82
+
83
+ def t(message, args = [])
84
+ unless I18n.get(message)
85
+ I18n.set(message, message) # just copy
86
+ end
87
+ I18n.t(message, args)
88
+ end
89
+
90
+ def confirm(message, args = [], default = true)
91
+ if @force
92
+ @logger.info t(message, args)
93
+ if default
94
+ @logger.info ' yes'
95
+ return true
96
+ else
97
+ @logger.info 'no'
98
+ return nil
99
+ end
100
+ end
101
+
102
+ loop do
103
+ print t(message, args)
104
+ if default
105
+ print ' [y]/n '
106
+ else
107
+ print ' y/[n] '
108
+ end
109
+ case gets.chomp.downcase
110
+ when 'yes', 'y'
111
+ return true
112
+ when 'no', 'n'
113
+ return nil
114
+ when ''
115
+ return default
116
+ end
117
+ end
118
+ end
119
+
120
+ def rewrite_yml(yml, key, val)
121
+ content = File.read(yml)
122
+ content.gsub!(/^(\s*)#{key}:.*$/, '\1' + "#{key}: #{val}")
123
+ if @backup
124
+ FileUtils.mv yml, "#{yml}-old"
125
+ end
126
+ File.write(yml, content)
127
+ end
128
+
129
+ def parse_options(args)
130
+ opts = OptionParser.new
131
+ opts.version = ReVIEW::VERSION
132
+ opts.banner = "Usage: #{File.basename($PROGRAM_NAME)} [option]"
133
+ opts.on('-h', '--help', 'print this message and quit.') do
134
+ puts opts.help
135
+ exit 0
136
+ end
137
+ opts.on('--latex-template name', 'specify LaTeX template name. (default: review-jsbook)') do |tname|
138
+ @specified_template = tname
139
+ end
140
+
141
+ begin
142
+ opts.parse!(args)
143
+ rescue OptionParser::ParseError => err
144
+ @logger.error err.message
145
+ $stderr.puts opts.help
146
+ raise ApplicationError
147
+ end
148
+
149
+ if @specified_template
150
+ tdir = File.join(@review_dir, 'templates/latex', @specified_template)
151
+ unless File.exist?(tdir)
152
+ @logger.error "!! #{tdir} not found. Aborted. !!"
153
+ raise ApplicationError
154
+ end
155
+ end
156
+ end
157
+
158
+ def parse_ymls(dir)
159
+ language = 'en'
160
+
161
+ Dir.glob(File.join(dir, '*.yml')).sort.each do |yml|
162
+ begin
163
+ config = YAML.load_file(yml)
164
+ if config['language'].present?
165
+ language = config['language']
166
+ end
167
+
168
+ if config['review_version'].present?
169
+ @config_ymls.push(yml)
170
+ end
171
+ if config['texdocumentclass'].present? ||
172
+ config['texcommand'].present? ||
173
+ config['texoptions'].present? ||
174
+ config['dvicommand'].present? ||
175
+ config['dvioptions'].present? ||
176
+ config['pdfmaker'].present?
177
+ @tex_ymls.push(yml)
178
+ end
179
+ if config['epubmaker'].present? || config['epubversion'].present? ||
180
+ config['htmlversion'].present?
181
+ @epub_ymls.push(yml)
182
+ end
183
+ if config['locale'].present?
184
+ @locale_ymls.push(yml)
185
+ end
186
+ if config['PREDEF'].present? || config['CHAPS'].present? ||
187
+ config['APPENDIX'].present? || config['POSTDEF'].present?
188
+ @catalog_ymls.push(yml)
189
+ end
190
+ rescue Psych::SyntaxError
191
+ @logger.error "!! #{yml} is broken. Ignored. !!"
192
+ end
193
+ end
194
+ I18n.setup(language)
195
+
196
+ @config_ymls.uniq!
197
+ @locale_ymls.uniq!
198
+ @catalog_ymls.uniq!
199
+ @tex_ymls.uniq!
200
+ @epub_ymls.uniq!
201
+ end
202
+
203
+ def check_old_catalogs(dir)
204
+ files = Dir.glob(File.join(dir, '*')).map do |fname|
205
+ if %w[PREDEF CHAPS POSTDEF PART].include?(File.basename(fname))
206
+ File.basename(fname)
207
+ else
208
+ return nil
209
+ end
210
+ end.compact
211
+
212
+ unless files.empty?
213
+ @logger.error t("!! %s file(s) is obsoleted. Run 'review-catalog-converter' to convert to 'catalog.yml' and remove old files. Aborted. !!", files.join(', '))
214
+ raise ApplicationError
215
+ end
216
+ end
217
+
218
+ def show_version
219
+ puts t('** review-update updates your project to %s **', ReVIEW::VERSION)
220
+ end
221
+
222
+ def check_own_files(dir)
223
+ if File.exist?(File.join(dir, 'layouts/layout.tex.erb'))
224
+ unless confirm('** There is custom layouts/layout.tex.erb file. Updating may break to make PDF until you fix layout.tex.erb. Do you really proceed to update? **', [], nil)
225
+ raise ApplicationError
226
+ end
227
+ end
228
+
229
+ if File.exist?(File.join(dir, 'review-ext.rb'))
230
+ @logger.info t('** There is review-ext.rb file. You need to update it by yourself. **')
231
+ end
232
+ end
233
+
234
+ def update_version
235
+ @config_ymls.each do |yml|
236
+ config = YAML.load_file(yml)
237
+ if config['review_version'].to_f == TARGET_VERSION.to_f
238
+ next
239
+ end
240
+
241
+ flag = true
242
+ if config['review_version'].to_f > TARGET_VERSION.to_f
243
+ flag = nil
244
+ end
245
+
246
+ if confirm("%s: Update '%s' to '%s'?", [File.basename(yml), 'review_version', TARGET_VERSION], flag)
247
+ rewrite_yml(yml, 'review_version', TARGET_VERSION)
248
+ end
249
+ end
250
+ end
251
+
252
+ def update_rakefile(dir)
253
+ taskdir = File.join(dir, 'lib/tasks')
254
+ unless File.exist?(taskdir)
255
+ FileUtils.mkdir_p taskdir
256
+ end
257
+
258
+ master_rakefile = File.join(@review_dir, 'samples/sample-book/src/Rakefile')
259
+
260
+ target_rakefile = File.join(dir, 'Rakefile')
261
+ if File.exist?(target_rakefile)
262
+ if Digest::SHA256.hexdigest(File.read(target_rakefile)) != Digest::SHA256.hexdigest(File.read(master_rakefile))
263
+ if confirm('%s will be overridden with Re:VIEW version (%s). Do you really proceed?', ['Rakefile', master_rakefile])
264
+ FileUtils.mv target_rakefile, "#{target_rakefile}-old"
265
+ FileUtils.cp master_rakefile, target_rakefile
266
+ end
267
+ end
268
+ else
269
+ FileUtils.cp master_rakefile, target_rakefile
270
+ end
271
+
272
+ master_rakefile = File.join(@review_dir, 'samples/sample-book/src/lib/tasks/review.rake')
273
+ target_rakefile = File.join(taskdir, 'review.rake')
274
+ if File.exist?(target_rakefile)
275
+ if Digest::SHA256.hexdigest(File.read(target_rakefile)) != Digest::SHA256.hexdigest(File.read(master_rakefile))
276
+ if confirm('%s will be overridden with Re:VIEW version (%s). Do you really proceed?', ['lib/tasks/review.rake', master_rakefile])
277
+ FileUtils.mv target_rakefile, "#{target_rakefile}-old"
278
+ FileUtils.cp master_rakefile, target_rakefile
279
+ end
280
+ end
281
+ else
282
+ FileUtils.cp master_rakefile, target_rakefile
283
+ end
284
+ end
285
+
286
+ def update_epub_version
287
+ @epub_ymls.each do |yml|
288
+ config = YAML.load_file(yml)
289
+ if config['epubversion'].present? && config['epubversion'].to_f < EPUB_VERSION.to_f
290
+ if confirm("%s: Update '%s' to '%s' from '%s'?", [File.basename(yml), 'epubversion', EPUB_VERSION, config['epubversion']])
291
+ rewrite_yml(yml, 'epubversion', EPUB_VERSION)
292
+ end
293
+ end
294
+ if !config['htmlversion'].present? || config['htmlversion'].to_f >= HTML_VERSION.to_f
295
+ next
296
+ end
297
+ if confirm("%s: Update '%s' to '%s' from '%s'?", [File.basename(yml), 'htmlversion', HTML_VERSION, config['htmlversion']])
298
+ rewrite_yml(yml, 'htmlversion', HTML_VERSION)
299
+ end
300
+ end
301
+ end
302
+
303
+ def update_locale
304
+ @locale_ymls.each do |yml|
305
+ config = YAML.load_file(yml)
306
+ if !config['chapter_quote'].present? || config['chapter_quote'].scan('%s').size != 1
307
+ next
308
+ end
309
+ v = config['chapter_quote'].sub('%s', '%s %s')
310
+ if confirm("%s: 'chapter_quote' now takes 2 values. Update '%s' to '%s'?", [File.basename(yml), config['chapter_quote'], v])
311
+ rewrite_yml(yml, 'chapter_quote', v)
312
+ end
313
+ end
314
+ end
315
+
316
+ def update_tex_parameters
317
+ @tex_ymls.each do |yml|
318
+ config = YAML.load_file(yml)
319
+ unless config['texdocumentclass']
320
+ next
321
+ end
322
+
323
+ if TEX_DOCUMENTCLASS.include?(config['texdocumentclass'][0])
324
+ if @specified_template.present? && config['texdocumentclass'][0] != @specified_template
325
+ # want to use other template?
326
+ @logger.error t("%s: !! 'texdocumentclass' uses new class '%s' already, but you specified '%s'. This tool can't handle such migration. Ignored. !!", [File.basename(yml), config['texdocumentclass'][0], @specified_template])
327
+ @template = nil
328
+ end
329
+ next
330
+ else
331
+ @template = config['texdocumentclass'][0]
332
+ end
333
+
334
+ if TEX_DOCUMENTCLASS_BAD.include?(config['texdocumentclass'][0])
335
+ cno = TEX_DOCUMENTCLASS_BAD.index(config['texdocumentclass'][0])
336
+
337
+ if @specified_template && @specified_template != TEX_DOCUMENTCLASS[cno]
338
+ # not default, manually selected
339
+ unless confirm("%s: 'texdocumentclass' uses the old class '%s'. By default it is migrated to '%s', but you specify '%s'. Do you really migrate 'texdocumentclass' to '%s'?",
340
+ [File.basename(yml), TEX_DOCUMENTCLASS_BAD[cno],
341
+ TEX_DOCUMENTCLASS[cno],
342
+ @specified_template, @specified_template])
343
+ @template = nil
344
+ next
345
+ end
346
+ @template = @specified_template
347
+ else
348
+ # default migration
349
+ @template = TEX_DOCUMENTCLASS[cno]
350
+ unless confirm("%s: 'texdocumentclass' uses the old class '%s'. By default it is migrated to '%s'. Do you really migrate 'texdocumentclass' to '%s'?", [File.basename(yml), TEX_DOCUMENTCLASS_BAD[cno], @template, @template])
351
+ @template = nil
352
+ next
353
+ end
354
+ end
355
+
356
+ flag, modified_opts = convert_documentclass_opts(yml, @template, config['texdocumentclass'][1])
357
+ if flag # successfully converted
358
+ @logger.info t("%s: previous 'texdocumentclass' option '%s' is safely replaced with '%s'.", [File.basename(yml), config['texdocumentclass'][1], modified_opts])
359
+ else # something wrong
360
+ unless confirm("%s: previous 'texdocumentclass' option '%s' couldn't be converted fully. '%s' is suggested. Do you really proceed?", [File.basename(yml), config['texdocumentclass'][1], modified_opts], nil)
361
+ @template = nil
362
+ next
363
+ end
364
+ end
365
+
366
+ rewrite_yml(yml, 'texdocumentclass', %Q(["#{@template}", "#{modified_opts}"]))
367
+ else
368
+ @template = nil
369
+ @logger.error t("%s: ** 'texdocumentclass' specifies '%s'. Because this is unknown class for this tool, you need to update it by yourself if it won't work. **", [File.basename(yml), config['texdocumentclass']])
370
+ end
371
+ end
372
+ end
373
+
374
+ def convert_documentclass_opts(yml, cls, prev_opts)
375
+ # XXX: at this time, review-jsbook and review-jlreq uses same parameters
376
+ opts = []
377
+ flag = true
378
+ case cls
379
+ when 'review-jsbook' # at this time, it ignores keyval
380
+ prev_opts.split(/\s*,\s*/).each do |v|
381
+ case v
382
+ when 'a4j', 'a5j', 'b4j', 'b5j', 'a3paper', 'a4paper', 'a5paper', 'a6paper', 'b4paper', 'b5paper', 'b6paper', 'letterpaper', 'legalpaper', 'executivepaper'
383
+ opts << "paper=#{v.sub('j', '').sub('paper', '')}"
384
+ when /[\d.]+ptj/ # not cared...
385
+ q = sprintf('%.2f', v.sub('pt', '').to_f * 1.4056)
386
+ opts << "Q=#{q}"
387
+ when /[\d.]+pt/
388
+ q = sprintf('%.2f', v.sub('pt', '').to_f * 1.4056)
389
+ opts << "Q=#{q}"
390
+ when /[\d.]+Q/
391
+ opts << "Q=#{v.sub('Q', '')}"
392
+ when 'landscape', 'oneside', 'twoside', 'vartwoside', 'onecolumn',
393
+ 'twocolumn', 'titlepage', 'notitlepage', 'openright',
394
+ 'openany', 'leqno', 'fleqn', 'disablejfam', 'draft', 'final',
395
+ 'mingoth', 'winjis', 'jis', 'papersize', 'english', 'report',
396
+ 'jslogo', 'nojslogo'
397
+ # pass-through
398
+ opts << v
399
+ when 'uplatex', 'nomag', 'usemag', 'nomag*', 'tombow', 'tombo', 'mentuke', 'autodetect-engine'
400
+ # can be ignored
401
+ next
402
+ else
403
+ flag = nil
404
+ end
405
+ end
406
+ opts << 'cameraready=print'
407
+ opts << 'cover=false'
408
+ when 'review-jlreq'
409
+ # at this time, only think about jsbook->jlreq
410
+ prev_opts.split(/\s*,\s*/).each do |v|
411
+ case v
412
+ when 'a4j', 'a5j', 'b4j', 'b5j', 'a3paper', 'a4paper', 'a5paper', 'a6paper', 'b4paper', 'b5paper', 'b6paper', 'letterpaper', 'legalpaper', 'executivepaper'
413
+ opts << "paper=#{v.sub('j', '').sub('paper', '')}"
414
+ when /[\d.]+ptj/ # not cared...
415
+ opts << "fontsize=#{v.sub('j', '')}"
416
+ when /[\d.]+pt/
417
+ opts << "fontsize=#{v}"
418
+ when /[\d.]+Q/
419
+ opts << "fontsize=#{v}"
420
+ when 'landscape', 'oneside', 'twoside', 'onecolumn', 'twocolumn', 'titlepage', 'notitlepage', 'openright', 'openany', 'leqno', 'fleqn', 'draft', 'final', 'report'
421
+ # pass-through
422
+ opts << v
423
+ when 'uplatex', 'nomag', 'usemag', 'nomag*', 'tombow', 'tombo', 'mentuke', 'autodetect-engine'
424
+ # can be ignored
425
+ next
426
+ else
427
+ # 'vartwoside', 'disablejfam', 'mingoth', 'winjis', 'jis', 'papersize', 'english', 'jslogo', 'nojslogo'
428
+ flag = nil
429
+ end
430
+ end
431
+ opts << 'cameraready=print'
432
+ opts << 'cover=false'
433
+ else
434
+ flag = nil
435
+ @logger.error t("%s: ** '%s' is unknown class. Ignored. **", [File.basename(yml), cls])
436
+ end
437
+ return flag, opts.join(',')
438
+ end
439
+
440
+ def update_tex_stys(template, dir)
441
+ texmacrodir = File.join(dir, 'sty')
442
+ unless File.exist?(texmacrodir)
443
+ FileUtils.mkdir texmacrodir
444
+ end
445
+
446
+ tdir = File.join(@review_dir, 'templates/latex', template)
447
+ Dir.glob(File.join(tdir, '*.*')).each do |master_styfile|
448
+ target_styfile = File.join(texmacrodir, File.basename(master_styfile))
449
+
450
+ unless File.exist?(target_styfile)
451
+ # just copy
452
+ FileUtils.cp master_styfile, target_styfile
453
+ next
454
+ end
455
+ if File.basename(target_styfile) == 'review-custom.sty'
456
+ next
457
+ end
458
+
459
+ if Digest::SHA256.hexdigest(File.read(target_styfile)) == Digest::SHA256.hexdigest(File.read(master_styfile))
460
+ # same
461
+ next
462
+ end
463
+
464
+ if confirm('%s will be overridden with Re:VIEW version (%s). Do you really proceed?', [target_styfile, master_styfile])
465
+ FileUtils.mv target_styfile, "#{target_styfile}-old"
466
+ FileUtils.cp master_styfile, target_styfile
467
+ end
468
+ end
469
+
470
+ if template == 'review-jsbook'
471
+ # provide gentombow from vendor/. current version is 2018/08/30 v0.9j
472
+ unless File.exist?(File.join(texmacrodir, 'gentombow09j.sty'))
473
+ FileUtils.cp File.join(@review_dir, 'vendor/gentombow/gentombow.sty'), File.join(texmacrodir, 'gentombow09j.sty')
474
+ end
475
+ end
476
+ end
477
+
478
+ def update_tex_command
479
+ @tex_ymls.each do |yml|
480
+ config = YAML.load_file(yml)
481
+ if !config['texcommand'] || config['texcommand'] !~ /\s+\-/
482
+ next
483
+ end
484
+ # option should be moved to texoptions
485
+ cmd, opts = config['texcommand'].split(/\s+\-/, 2)
486
+ opts = "-#{opts}"
487
+
488
+ unless confirm("%s: 'texcommand' has options ('%s'). Move it to 'texoptions'?", [File.basename(yml), opts])
489
+ next
490
+ end
491
+
492
+ if config['texoptions'].present?
493
+ config['texoptions'] += " #{opts}"
494
+ rewrite_yml(yml, 'texcommand', %Q("#{cmd}"))
495
+ rewrite_yml(yml, 'texoptions', %Q("#{config['texoptions']}"))
496
+ else
497
+ rewrite_yml(yml, 'texcommand', %Q("#{cmd}"\ntexoptions: "#{TEX_OPTIONS} #{opts}"))
498
+ end
499
+ end
500
+ end
501
+
502
+ def update_dvi_command
503
+ @tex_ymls.each do |yml|
504
+ config = YAML.load_file(yml)
505
+ if !config['dvicommand'] || config['dvicommand'] !~ /\s+\-/
506
+ next
507
+ end
508
+
509
+ # option should be moved to dvioptions
510
+ cmd, opts = config['dvicommand'].split(/\s+\-/, 2)
511
+ opts = "-#{opts}"
512
+
513
+ unless confirm("%s: 'dvicommand' has options ('%s'). Move it to 'dvioptions'?", [File.basename(yml), opts])
514
+ next
515
+ end
516
+
517
+ if config['dvioptions'].present?
518
+ config['dvioptions'] += " #{opts}"
519
+ rewrite_yml(yml, 'dvicommand', %Q("#{cmd}"))
520
+ rewrite_yml(yml, 'dvioptions', %Q("#{config['dvioptions']}"))
521
+ else
522
+ rewrite_yml(yml, 'dvicommand', %Q("#{cmd}"\ndvioptions: "#{DVI_OPTIONS} #{opts}"))
523
+ end
524
+ end
525
+ end
526
+ end
527
+ end