review 5.0.0 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-tex.yml +35 -0
  3. data/.github/workflows/ruby-win.yml +8 -4
  4. data/.github/workflows/ruby.yml +6 -2
  5. data/.rubocop.yml +24 -9
  6. data/NEWS.ja.md +215 -0
  7. data/NEWS.md +215 -1
  8. data/README.md +7 -6
  9. data/Rakefile +7 -2
  10. data/bin/review +2 -4
  11. data/bin/review-catalog-converter +3 -3
  12. data/bin/review-check +6 -8
  13. data/bin/review-checkdep +1 -4
  14. data/bin/review-compile +10 -20
  15. data/bin/review-epub2html +1 -4
  16. data/bin/review-epubmaker +3 -4
  17. data/bin/review-idgxmlmaker +1 -3
  18. data/bin/review-index +11 -5
  19. data/bin/review-init +1 -4
  20. data/bin/review-pdfmaker +1 -3
  21. data/bin/review-preproc +30 -38
  22. data/bin/review-textmaker +1 -3
  23. data/bin/review-update +1 -4
  24. data/bin/review-validate +3 -3
  25. data/bin/review-vol +1 -4
  26. data/bin/review-webmaker +1 -3
  27. data/doc/config.yml.sample +23 -5
  28. data/doc/config.yml.sample-simple +1 -1
  29. data/doc/format.ja.md +49 -12
  30. data/doc/format.md +52 -12
  31. data/doc/quickstart.ja.md +11 -1
  32. data/doc/quickstart.md +11 -2
  33. data/doc/writing_vertical.ja.md +6 -0
  34. data/lib/review/book/base.rb +4 -0
  35. data/lib/review/book/book_unit.rb +15 -2
  36. data/lib/review/book/chapter.rb +3 -0
  37. data/lib/review/book/index.rb +5 -1
  38. data/lib/review/book/volume.rb +1 -0
  39. data/lib/review/builder.rb +90 -54
  40. data/lib/review/call_hook.rb +20 -0
  41. data/lib/review/catalog.rb +2 -0
  42. data/lib/review/compiler.rb +88 -52
  43. data/lib/review/configure.rb +64 -7
  44. data/lib/review/epubmaker/content.rb +113 -0
  45. data/lib/review/epubmaker/epubcommon.rb +372 -0
  46. data/lib/review/epubmaker/epubv2.rb +178 -0
  47. data/lib/review/epubmaker/epubv3.rb +231 -0
  48. data/lib/review/epubmaker/producer.rb +167 -0
  49. data/lib/review/epubmaker/reviewheaderlistener.rb +12 -2
  50. data/lib/review/epubmaker/zip_exporter.rb +84 -0
  51. data/lib/review/epubmaker.rb +114 -129
  52. data/lib/review/exception.rb +13 -0
  53. data/lib/review/htmlbuilder.rb +109 -67
  54. data/lib/review/htmlutils.rb +1 -1
  55. data/lib/review/i18n.rb +1 -0
  56. data/lib/review/i18n.yml +6 -0
  57. data/lib/review/idgxmlbuilder.rb +72 -48
  58. data/lib/review/idgxmlmaker.rb +15 -14
  59. data/lib/review/img_math.rb +239 -0
  60. data/lib/review/index_builder.rb +90 -32
  61. data/lib/review/init.rb +4 -4
  62. data/lib/review/latexbox.rb +58 -0
  63. data/lib/review/latexbuilder.rb +79 -58
  64. data/lib/review/latexutils.rb +9 -1
  65. data/lib/review/lineinput.rb +112 -2
  66. data/lib/review/loggable.rb +27 -0
  67. data/lib/review/logger.rb +89 -2
  68. data/lib/review/makerhelper.rb +7 -206
  69. data/lib/review/markdownbuilder.rb +44 -4
  70. data/lib/review/pdfmaker.rb +70 -51
  71. data/lib/review/plaintextbuilder.rb +20 -11
  72. data/lib/review/preprocessor/directive.rb +35 -0
  73. data/lib/review/preprocessor/line.rb +34 -0
  74. data/lib/review/preprocessor/repository.rb +177 -0
  75. data/lib/review/preprocessor.rb +105 -301
  76. data/lib/review/rstbuilder.rb +13 -4
  77. data/lib/review/sec_counter.rb +1 -0
  78. data/lib/review/template.rb +11 -1
  79. data/lib/review/textmaker.rb +23 -20
  80. data/lib/review/textutils.rb +10 -17
  81. data/lib/review/tocprinter.rb +93 -71
  82. data/lib/review/topbuilder.rb +44 -19
  83. data/lib/review/update.rb +5 -6
  84. data/lib/review/version.rb +1 -1
  85. data/lib/review/volumeprinter.rb +11 -12
  86. data/lib/review/webmaker.rb +31 -27
  87. data/lib/review/webtocprinter.rb +10 -9
  88. data/lib/review/yamlloader.rb +2 -1
  89. data/lib/review.rb +1 -1
  90. data/review.gemspec +5 -3
  91. data/samples/sample-book/src/config-epub2.yml +1 -1
  92. data/samples/sample-book/src/config.yml +1 -1
  93. data/samples/sample-book/src/lib/tasks/review.rake +19 -1
  94. data/samples/sample-book/src/lib/tasks/z01_copy_sty.rake +2 -1
  95. data/samples/syntax-book/ch01.re +1 -1
  96. data/samples/syntax-book/ch02.re +30 -6
  97. data/samples/syntax-book/ch03.re +1 -1
  98. data/samples/syntax-book/images/img3-2.png +0 -0
  99. data/samples/syntax-book/lib/tasks/z01_copy_sty.rake +2 -1
  100. data/templates/html/_colophon.html.erb +23 -0
  101. data/templates/html/_colophon_history.html.erb +9 -0
  102. data/templates/html/_cover.html.erb +10 -0
  103. data/templates/html/_part_body.html.erb +6 -0
  104. data/templates/html/_titlepage.html.erb +20 -0
  105. data/templates/html/layout-html5.html.erb +6 -0
  106. data/templates/html/layout-xhtml1.html.erb +6 -0
  107. data/templates/latex/config.erb +11 -0
  108. data/templates/latex/review-jlreq/review-base.sty +7 -9
  109. data/templates/latex/review-jlreq/review-jlreq.cls +48 -6
  110. data/templates/latex/review-jlreq/review-style.sty +6 -1
  111. data/templates/latex/review-jlreq/review-tcbox.sty +348 -0
  112. data/templates/latex/review-jlreq/reviewmacro.sty +5 -0
  113. data/templates/latex/review-jsbook/review-base.sty +13 -9
  114. data/templates/latex/review-jsbook/review-jsbook.cls +41 -6
  115. data/templates/latex/review-jsbook/review-style.sty +6 -1
  116. data/templates/latex/review-jsbook/review-tcbox.sty +348 -0
  117. data/templates/latex/review-jsbook/reviewmacro.sty +5 -0
  118. data/templates/opf/epubv2.opf.erb +7 -7
  119. data/templates/opf/epubv3.opf.erb +7 -7
  120. data/templates/opf/opf_manifest_epubv2.opf.erb +10 -0
  121. data/templates/opf/opf_manifest_epubv3.opf.erb +10 -0
  122. data/templates/opf/opf_metainfo_epubv2.opf.erb +17 -0
  123. data/templates/opf/opf_metainfo_epubv3.opf.erb +49 -0
  124. data/templates/opf/opf_tocx_epubv2.opf.erb +9 -0
  125. data/templates/opf/opf_tocx_epubv3.opf.erb +17 -0
  126. data/templates/web/html/layout-html5.html.erb +6 -5
  127. data/templates/web/html/layout-xhtml1.html.erb +6 -0
  128. data/test/assets/header_listener.html +35 -0
  129. data/test/assets/img_math/img1.png +0 -0
  130. data/test/assets/img_math/img2.png +0 -0
  131. data/test/assets/img_math/img3.png +0 -0
  132. data/test/assets/syntax_book_index_detail.txt +60 -0
  133. data/test/assets/test_template.tex +7 -1
  134. data/test/assets/test_template_backmatter.tex +7 -1
  135. data/test/run_test.rb +1 -1
  136. data/test/test_book_chapter.rb +27 -4
  137. data/test/test_builder.rb +10 -8
  138. data/test/test_catalog_converter_cmd.rb +1 -1
  139. data/test/test_epub3maker.rb +168 -124
  140. data/test/test_epubmaker.rb +248 -131
  141. data/test/test_epubmaker_cmd.rb +15 -4
  142. data/test/test_helper.rb +5 -4
  143. data/test/test_htmlbuilder.rb +170 -31
  144. data/test/test_idgxmlbuilder.rb +44 -23
  145. data/test/test_idgxmlmaker_cmd.rb +7 -3
  146. data/test/test_img_math.rb +111 -0
  147. data/test/test_index.rb +30 -4
  148. data/test/test_indexbuilder.rb +5 -5
  149. data/test/test_latexbuilder.rb +151 -26
  150. data/test/test_latexbuilder_v2.rb +18 -10
  151. data/test/test_lineinput.rb +20 -93
  152. data/test/test_markdownbuilder.rb +42 -0
  153. data/test/test_pdfmaker.rb +90 -0
  154. data/test/test_pdfmaker_cmd.rb +2 -2
  155. data/test/test_plaintextbuilder.rb +56 -40
  156. data/test/test_preprocessor.rb +188 -1
  157. data/test/test_reviewheaderlistener.rb +49 -0
  158. data/test/test_rstbuilder.rb +13 -0
  159. data/test/test_template.rb +12 -2
  160. data/test/test_textmaker_cmd.rb +5 -1
  161. data/test/test_tocprinter.rb +46 -0
  162. data/test/test_topbuilder.rb +50 -19
  163. data/test/test_update.rb +34 -34
  164. data/test/test_zip_exporter.rb +5 -6
  165. metadata +95 -17
  166. data/lib/epubmaker/content.rb +0 -111
  167. data/lib/epubmaker/epubcommon.rb +0 -449
  168. data/lib/epubmaker/epubv2.rb +0 -142
  169. data/lib/epubmaker/epubv3.rb +0 -235
  170. data/lib/epubmaker/producer.rb +0 -375
  171. data/lib/epubmaker/zip_exporter.rb +0 -81
  172. data/lib/epubmaker.rb +0 -23
  173. data/lib/lineinput.rb +0 -155
@@ -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
@@ -16,10 +16,13 @@ require 'review/yamlloader'
16
16
  require 'review/topbuilder'
17
17
  require 'review/version'
18
18
  require 'review/makerhelper'
19
+ require 'review/img_math'
20
+ require 'review/loggable'
19
21
 
20
22
  module ReVIEW
21
23
  class TEXTMaker
22
24
  include MakerHelper
25
+ include Loggable
23
26
 
24
27
  attr_accessor :config, :basedir
25
28
 
@@ -27,15 +30,8 @@ module ReVIEW
27
30
  @basedir = nil
28
31
  @logger = ReVIEW.logger
29
32
  @plaintext = nil
30
- end
31
-
32
- def error(msg)
33
- @logger.error msg
34
- exit 1
35
- end
36
-
37
- def warn(msg)
38
- @logger.warn msg
33
+ @img_math = nil
34
+ @compile_errors = nil
39
35
  end
40
36
 
41
37
  def self.execute(*args)
@@ -70,29 +66,31 @@ module ReVIEW
70
66
  end
71
67
 
72
68
  def remove_old_files(path)
73
- cleanup_mathimg('_review_math_text')
69
+ @img_math.cleanup_mathimg
74
70
  FileUtils.rm_rf(path)
75
71
  end
76
72
 
77
73
  def execute(*args)
78
74
  cmd_config, yamlfile = parse_opts(args)
79
- error "#{yamlfile} not found." unless File.exist?(yamlfile)
75
+ error! "#{yamlfile} not found." unless File.exist?(yamlfile)
80
76
 
81
77
  @config = ReVIEW::Configure.create(maker: 'textmaker',
82
78
  yamlfile: yamlfile,
83
79
  config: cmd_config)
80
+ @img_math = ReVIEW::ImgMath.new(@config, path_name: '_review_math_text')
84
81
 
85
82
  I18n.setup(@config['language'])
86
83
  begin
87
84
  generate_text_files(yamlfile)
85
+ @logger.success("built #{build_path}")
88
86
  rescue ApplicationError => e
89
87
  raise if @config['debug']
90
- error(e.message)
88
+
89
+ error! e.message
91
90
  end
92
91
 
93
- math_dir = "./#{@config['imagedir']}/_review_math_text"
94
- if @config['imgmath'] && File.exist?(File.join(math_dir, '__IMGMATH_BODY__.map'))
95
- make_math_images(math_dir)
92
+ if @config['math_format'] == 'imgmath'
93
+ @img_math.make_math_images
96
94
  end
97
95
  end
98
96
 
@@ -105,15 +103,19 @@ module ReVIEW
105
103
  @book = ReVIEW::Book::Base.new(@basedir, config: @config)
106
104
 
107
105
  build_body(@path, yamlfile)
106
+
107
+ if @compile_errors
108
+ app_error 'compile error, No TEXT file output.'
109
+ end
108
110
  end
109
111
 
110
112
  def build_body(basetmpdir, _yamlfile)
111
113
  base_path = Pathname.new(@basedir)
112
114
  builder = nil
113
115
  if @plaintext
114
- builder = ReVIEW::PLAINTEXTBuilder.new
116
+ builder = ReVIEW::PLAINTEXTBuilder.new(img_math: @img_math)
115
117
  else
116
- builder = ReVIEW::TOPBuilder.new
118
+ builder = ReVIEW::TOPBuilder.new(img_math: @img_math)
117
119
  end
118
120
  @converter = ReVIEW::Converter.new(@book, builder)
119
121
  @book.parts.each do |part|
@@ -158,8 +160,9 @@ module ReVIEW
158
160
  begin
159
161
  @converter.convert(filename, File.join(basetmpdir, textfile))
160
162
  rescue => e
161
- warn "compile error in #{filename} (#{e.class})"
162
- warn e.message
163
+ @compile_errors = true
164
+ error "compile error in #{filename} (#{e.class})"
165
+ error e.message
163
166
  end
164
167
  end
165
168
  end
@@ -15,7 +15,7 @@ module ReVIEW
15
15
  add = 0
16
16
  len = nil
17
17
  str.gsub("\t") do
18
- len = ts - ($`.size + add) % ts
18
+ len = ts - (($`.size + add) % ts)
19
19
  add += len - 1
20
20
  ' ' * len
21
21
  end
@@ -51,6 +51,7 @@ module ReVIEW
51
51
  if tail.nil? || head.nil?
52
52
  return nil
53
53
  end
54
+
54
55
  space = true
55
56
  # rule 2
56
57
  if %i[F W H].include?(Unicode::Eaw.property(tail)) &&
@@ -71,12 +72,13 @@ module ReVIEW
71
72
  end
72
73
 
73
74
  # lazy than rule 3, but it looks better
74
- if lazy &&
75
- (%i[F W H].include?(Unicode::Eaw.property(tail)) &&
76
- tail !~ /\p{Hangul}/) ||
77
- (%i[F W H].include?(Unicode::Eaw.property(head)) &&
78
- head !~ /\p{Hangul}/)
79
- space = nil
75
+ if lazy
76
+ if (%i[F W H].include?(Unicode::Eaw.property(tail)) &&
77
+ tail !~ /\p{Hangul}/) ||
78
+ (%i[F W H].include?(Unicode::Eaw.property(head)) &&
79
+ head !~ /\p{Hangul}/)
80
+ space = nil
81
+ end
80
82
  end
81
83
  end
82
84
  space
@@ -86,6 +88,7 @@ module ReVIEW
86
88
  unless @book.config['join_lines_by_lang']
87
89
  return lines.join
88
90
  end
91
+
89
92
  lazy = true
90
93
  lang = 'ja'
91
94
  0.upto(lines.size - 2) do |n|
@@ -96,16 +99,6 @@ module ReVIEW
96
99
  lines.join
97
100
  end
98
101
 
99
- def defer_math_image(str, path, key)
100
- # for Re:VIEW >3
101
- File.open(File.join(File.dirname(path), "__IMGMATH_BODY__#{key}.tex"), 'w') do |f|
102
- f.puts str
103
- end
104
- File.open(File.join(File.dirname(path), '__IMGMATH_BODY__.map'), 'a+') do |f|
105
- f.puts key
106
- end
107
- end
108
-
109
102
  private
110
103
 
111
104
  # remove elements at the back of `lines` if element is empty string
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2008-2020 Minero Aoki, Kenshi Muto
1
+ # Copyright (c) 2008-2021 Minero Aoki, Kenshi Muto
2
2
  # 1999-2007 Minero Aoki
3
3
  #
4
4
  # This program is free software.
@@ -36,34 +36,50 @@ module ReVIEW
36
36
  end
37
37
 
38
38
  class TOCPrinter
39
- def self.execute(*args)
40
- Signal.trap(:INT) { exit 1 }
41
- if RUBY_PLATFORM !~ /mswin(?!ce)|mingw|cygwin|bccwin/
42
- Signal.trap(:PIPE, 'IGNORE')
39
+ class Counter
40
+ def initialize(name: nil, level: nil, headline: nil, lines: nil, chars: nil, list_lines: nil, text_lines: nil, part: nil)
41
+ @name = name
42
+ @level = level
43
+ @headline = headline
44
+ @lines = lines
45
+ @chars = chars
46
+ @list_lines = list_lines
47
+ @text_lines = text_lines
48
+ @part = part
43
49
  end
50
+
51
+ attr_accessor :name, :level, :headline, :lines, :chars, :list_lines, :text_lines, :part
52
+ end
53
+
54
+ def self.execute(*args)
44
55
  new.execute(*args)
45
- rescue Errno::EPIPE
46
- exit 0
47
56
  end
48
57
 
49
58
  def initialize
50
59
  @logger = ReVIEW.logger
51
- @config = ReVIEW::Configure.values
52
60
  @yamlfile = 'config.yml'
53
- @book = ReVIEW::Book::Base.new('.', config: @config)
54
61
  @upper = 4
55
62
  @indent = true
56
63
  @buildonly = nil
57
64
  @detail = nil
65
+ @calc_char_width = nil
58
66
  end
59
67
 
68
+ attr_accessor :calc_char_width
69
+
60
70
  def execute(*args)
61
71
  parse_options(args)
62
- unless File.readable?(@yamlfile)
63
- @logger.error("No such fiile or can't open #{@yamlfile}.")
72
+ begin
73
+ @config = ReVIEW::Configure.create(yamlfile: @yamlfile)
74
+ @book = ReVIEW::Book::Base.new('.', config: @config)
75
+ unless File.readable?(@yamlfile)
76
+ raise ReVIEW::FileNotFound, "No such fiile or can't open #{@yamlfile}."
77
+ end
78
+ rescue ReVIEW::ConfigError, ReVIEW::FileNotFound, ReVIEW::CompileError, ReVIEW::ApplicationError => e
79
+ @logger.error e.message
64
80
  exit 1
65
81
  end
66
- @book.load_config(@yamlfile)
82
+
67
83
  I18n.setup(@config['language'])
68
84
 
69
85
  if @detail
@@ -84,27 +100,27 @@ module ReVIEW
84
100
  begin
85
101
  @book.parts.each do |part|
86
102
  if part.name.present? && (@buildonly.nil? || @buildonly.include?(part.name))
87
- result_array.push({ part: 'start' })
103
+ result_array.push(Counter.new(part: 'start'))
88
104
  if part.file?
89
- result = build_chap(part)
90
- result_array += parse_contents(part.name, @upper, result)
105
+ content = build_chap(part)
106
+ result_array.concat(parse_contents(part.name, @upper, content))
91
107
  else
92
108
  title = part.format_number + I18n.t('chapter_postfix') + part.title
93
- result_array += [
94
- { name: '', lines: 1, chars: title.size, list_lines: 0, text_lines: 1 },
95
- { level: 0, headline: title, lines: 1, chars: title.size, list_lines: 0, text_lines: 1 }
96
- ]
109
+ result_array.push(
110
+ Counter.new(name: '', lines: 1, chars: title.size, list_lines: 0, text_lines: 1),
111
+ Counter.new(level: 0, headline: title, lines: 1, chars: title.size, list_lines: 0, text_lines: 1)
112
+ )
97
113
  end
98
114
  end
99
115
 
100
116
  part.chapters.each do |chap|
101
117
  if @buildonly.nil? || @buildonly.include?(chap.name)
102
- result = build_chap(chap)
103
- result_array += parse_contents(chap.name, @upper, result)
118
+ content = build_chap(chap)
119
+ result_array.concat(parse_contents(chap.name, @upper, content))
104
120
  end
105
121
  end
106
122
  if part.name.present? && (@buildonly.nil? || @buildonly.include?(part.name))
107
- result_array.push({ part: 'end' })
123
+ result_array.push(Counter.new(part: 'end'))
108
124
  end
109
125
  end
110
126
  rescue ReVIEW::FileNotFound, ReVIEW::CompileError => e
@@ -117,15 +133,15 @@ module ReVIEW
117
133
 
118
134
  def print_result(result_array)
119
135
  result_array.each do |result|
120
- if result[:part]
136
+ if result.part
121
137
  next
122
138
  end
123
139
 
124
- if result[:name]
140
+ if result.name
125
141
  # file information
126
142
  if @detail
127
143
  puts '============================='
128
- printf("%6dC %5dL %5dP %s\n", result[:chars], result[:lines], calc_pages(result).ceil, result[:name])
144
+ printf("%6dC %5dL %5dP %s\n", result.chars, result.lines, calc_pages(result).ceil, result.name)
129
145
  puts '-----------------------------'
130
146
  end
131
147
  next
@@ -133,42 +149,39 @@ module ReVIEW
133
149
 
134
150
  # section information
135
151
  if @detail
136
- printf('%6dC %5dL %5.1fP ', result[:chars], result[:lines], calc_pages(result))
152
+ printf('%6dC %5dL %5.1fP ', result.chars, result.lines, calc_pages(result))
137
153
  end
138
- if @indent && result[:level]
139
- print ' ' * (result[:level] == 0 ? 0 : result[:level] - 1)
154
+ if @indent && result.level
155
+ print ' ' * (result.level == 0 ? 0 : result.level - 1)
140
156
  end
141
- puts result[:headline]
157
+ puts result.headline
142
158
  end
143
159
  end
144
160
 
145
161
  def calc_pages(result)
146
- p = 0
147
- p += result[:list_lines].to_f / @book.page_metric.list.n_lines
148
- p += result[:text_lines].to_f / @book.page_metric.text.n_lines
149
- p
162
+ (result.list_lines.to_f / @book.page_metric.list.n_lines) +
163
+ (result.text_lines.to_f / @book.page_metric.text.n_lines)
150
164
  end
151
165
 
152
- def calc_linesize(l)
153
- return l.size unless @calc_char_width
154
- w = 0
155
- l.split('').each do |c|
166
+ def calc_linesize(line)
167
+ return line.size unless @calc_char_width
168
+
169
+ line.each_char.inject(0) do |result, char|
156
170
  # XXX: should include A also?
157
- if %i[Na H N].include?(Unicode::Eaw.property(c))
158
- w += 0.5 # halfwidth
171
+ if %i[Na H N].include?(Unicode::Eaw.property(char))
172
+ result + 0.5 # halfwidth
159
173
  else
160
- w += 1
174
+ result + 1
161
175
  end
162
176
  end
163
- w
164
177
  end
165
178
 
166
179
  def parse_contents(name, upper, content)
167
180
  headline_array = []
168
- counter = { lines: 0, chars: 0, list_lines: 0, text_lines: 0 }
181
+ counter = Counter.new(lines: 0, chars: 0, list_lines: 0, text_lines: 0)
169
182
  listmode = nil
170
183
 
171
- content.split("\n").each do |l|
184
+ content.each_line(chomp: true) do |l|
172
185
  if l.start_with?("\x01STARTLIST\x01")
173
186
  listmode = true
174
187
  next
@@ -180,58 +193,67 @@ module ReVIEW
180
193
  level = $1.to_i
181
194
  l = $'
182
195
  if level <= upper
183
- if counter[:chars] > 0
196
+ if counter.chars > 0
184
197
  headline_array.push(counter)
185
198
  end
186
199
  headline = l
187
- counter = {
200
+ counter = Counter.new(
188
201
  level: level,
189
202
  headline: headline,
190
203
  lines: 1,
191
204
  chars: headline.size,
192
205
  list_lines: 0,
193
206
  text_lines: 1
194
- }
207
+ )
195
208
  next
196
209
  end
197
210
  end
198
211
 
199
- counter[:lines] += 1
200
- counter[:chars] += l.size
212
+ counter.lines += 1
213
+ counter.chars += l.size
201
214
 
202
215
  if listmode
203
216
  # code list: calculate line wrapping
204
- if l.size == 0
205
- counter[:list_lines] += 1
206
- else
207
- counter[:list_lines] += (calc_linesize(l) - 1) / @book.page_metric.list.n_columns + 1
208
- end
217
+ counter.list_lines += calc_line_wrapping(l, mode: :list)
209
218
  else
210
219
  # normal paragraph: calculate line wrapping
211
- if l.size == 0
212
- counter[:text_lines] += 1
213
- else
214
- counter[:text_lines] += (calc_linesize(l) - 1) / @book.page_metric.text.n_columns + 1
215
- end
220
+ counter.text_lines += calc_line_wrapping(l, mode: :text)
216
221
  end
217
222
  end
218
223
  headline_array.push(counter)
219
224
 
220
- total_lines = 0
221
- total_chars = 0
222
- total_list_lines = 0
223
- total_text_lines = 0
225
+ total = calc_total_count(name, headline_array)
226
+ headline_array.unshift(total)
227
+ end
228
+
229
+ def calc_line_wrapping(line, mode:)
230
+ return 1 if line.size == 0
231
+
232
+ case mode
233
+ when :list
234
+ ((calc_linesize(line) - 1) / @book.page_metric.list.n_columns) + 1
235
+ else # mode == :text
236
+ ((calc_linesize(line) - 1) / @book.page_metric.text.n_columns) + 1
237
+ end
238
+ end
239
+
240
+ def calc_total_count(name, headline_array)
241
+ total = Counter.new(name: name,
242
+ lines: 0,
243
+ chars: 0,
244
+ list_lines: 0,
245
+ text_lines: 0)
224
246
 
225
247
  headline_array.each do |h|
226
- next unless h[:lines]
227
- total_lines += h[:lines]
228
- total_chars += h[:chars]
229
- total_list_lines += h[:list_lines]
230
- total_text_lines += h[:text_lines]
248
+ next unless h.lines
249
+
250
+ total.lines += h.lines
251
+ total.chars += h.chars
252
+ total.list_lines += h.list_lines
253
+ total.text_lines += h.text_lines
231
254
  end
232
255
 
233
- headline_array.delete_if(&:empty?).
234
- unshift({ name: name, lines: total_lines, chars: total_chars, list_lines: total_list_lines, text_lines: total_text_lines })
256
+ total
235
257
  end
236
258
 
237
259
  def build_chap(chap)
@@ -239,8 +261,8 @@ module ReVIEW
239
261
  begin
240
262
  compiler.compile(@book.chapter(chap.name))
241
263
  rescue ReVIEW::ApplicationError => e
242
- @logger.error e
243
- exit 1
264
+ @logger.error e.message
265
+ ''
244
266
  end
245
267
  end
246
268
 
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2008-2020 Minero Aoki, Kenshi Muto
1
+ # Copyright (c) 2008-2021 Minero Aoki, Kenshi Muto
2
2
  # 2002-2006 Minero Aoki
3
3
  #
4
4
  # This program is free software.
@@ -78,7 +78,7 @@ module ReVIEW
78
78
 
79
79
  def dd(lines)
80
80
  split_paragraph(lines).each do |paragraph|
81
- puts "\t#{paragraph.gsub(/\n/, '')}"
81
+ puts "\t#{paragraph.delete("\n")}"
82
82
  end
83
83
  end
84
84
 
@@ -105,7 +105,7 @@ module ReVIEW
105
105
  list_header(id, caption, lang)
106
106
  end
107
107
  rescue KeyError
108
- error "no such list: #{id}"
108
+ app_error "no such list: #{id}"
109
109
  end
110
110
  puts "◆→終了:#{@titles['list']}←◆"
111
111
  blank
@@ -178,7 +178,7 @@ module ReVIEW
178
178
  list_header(id, caption, lang)
179
179
  end
180
180
  rescue KeyError
181
- error "no such list: #{id}"
181
+ app_error "no such list: #{id}"
182
182
  end
183
183
  puts "◆→終了:#{@titles['list']}←◆"
184
184
  blank
@@ -202,7 +202,7 @@ module ReVIEW
202
202
  if @chapter.image_bound?(id)
203
203
  puts "◆→#{@chapter.image(id).path}#{metrics}←◆"
204
204
  else
205
- warn "image not bound: #{id}"
205
+ warn "image not bound: #{id}", location: location
206
206
  lines.each do |line|
207
207
  puts line
208
208
  end
@@ -228,15 +228,12 @@ module ReVIEW
228
228
  puts "◆→開始:#{@titles['texequation']}←◆"
229
229
  texequation_header(id, caption) if caption_top?('equation')
230
230
 
231
- if @book.config['imgmath']
231
+ if @book.config['math_format'] == 'imgmath'
232
232
  fontsize = @book.config['imgmath_options']['fontsize'].to_f
233
233
  lineheight = @book.config['imgmath_options']['lineheight'].to_f
234
234
  math_str = "\\begin{equation*}\n\\fontsize{#{fontsize}}{#{lineheight}}\\selectfont\n#{lines.join("\n")}\n\\end{equation*}\n"
235
235
  key = Digest::SHA256.hexdigest(math_str)
236
- math_dir = File.join(@book.config['imagedir'], '_review_math_text')
237
- Dir.mkdir(math_dir) unless Dir.exist?(math_dir)
238
- img_path = File.join(math_dir, "_gen_#{key}.#{@book.config['imgmath_options']['format']}")
239
- defer_math_image(math_str, img_path, key)
236
+ img_path = @img_math.defer_math_image(math_str, key)
240
237
  puts "◆→math:#{File.basename(img_path)}←◆"
241
238
  else
242
239
  puts lines.join("\n")
@@ -274,6 +271,7 @@ module ReVIEW
274
271
 
275
272
  def comment(lines, comment = nil)
276
273
  return unless @book.config['draft']
274
+
277
275
  lines ||= []
278
276
  unless comment.blank?
279
277
  lines.unshift(comment)
@@ -289,7 +287,25 @@ module ReVIEW
289
287
  def inline_fn(id)
290
288
  "【注#{@chapter.footnote(id).number}】"
291
289
  rescue KeyError
292
- error "unknown footnote: #{id}"
290
+ app_error "unknown footnote: #{id}"
291
+ end
292
+
293
+ def inline_endnote(id)
294
+ "【後注#{@chapter.endnote(id).number}】"
295
+ rescue KeyError
296
+ app_error "unknown endnote: #{id}"
297
+ end
298
+
299
+ def endnote_begin
300
+ puts '◆→開始:後注←◆'
301
+ end
302
+
303
+ def endnote_end
304
+ puts '◆→終了:後注←◆'
305
+ end
306
+
307
+ def endnote_item(id)
308
+ puts "【後注#{@chapter.endnote(id).number}】#{compile_inline(@chapter.endnote(id).content)}"
293
309
  end
294
310
 
295
311
  def compile_ruby(base, ruby)
@@ -367,11 +383,23 @@ module ReVIEW
367
383
  "@#{str}@◆→@〜@部分に下線←◆"
368
384
  end
369
385
 
386
+ def inline_ins(str)
387
+ "◆→開始:挿入表現←◆#{str}◆→終了:挿入表現←◆"
388
+ end
389
+
390
+ def inline_del(str)
391
+ "◆→開始:削除表現←◆#{str}◆→終了:削除表現←◆"
392
+ end
393
+
394
+ def inline_tcy(str)
395
+ "◆→開始:回転←◆#{str}◆→終了:縦回転←◆"
396
+ end
397
+
370
398
  def inline_icon(id)
371
399
  begin
372
400
  "◆→画像 #{@chapter.image(id).path.sub(%r{\A\./}, '')}←◆"
373
401
  rescue
374
- warn "image not bound: #{id}"
402
+ warn "image not bound: #{id}", location: location
375
403
  "◆→画像 #{id}←◆"
376
404
  end
377
405
  end
@@ -397,13 +425,10 @@ module ReVIEW
397
425
  end
398
426
 
399
427
  def inline_m(str)
400
- if @book.config['imgmath']
428
+ if @book.config['math_format'] == 'imgmath'
401
429
  math_str = '$' + str + '$'
402
430
  key = Digest::SHA256.hexdigest(str)
403
- math_dir = File.join(@book.config['imagedir'], '_review_math_text')
404
- Dir.mkdir(math_dir) unless Dir.exist?(math_dir)
405
- img_path = File.join(math_dir, "_gen_#{key}.#{@book.config['imgmath_options']['format']}")
406
- defer_math_image(math_str, img_path, key)
431
+ img_path = @img_math.defer_math_image(math_str, key)
407
432
  %Q(◆→TeX式ここから←◆◆→math:#{File.basename(img_path)}←◆◆→TeX式ここまで←◆)
408
433
  else
409
434
  %Q(◆→TeX式ここから←◆#{str}◆→TeX式ここまで←◆)
@@ -418,7 +443,7 @@ module ReVIEW
418
443
  def inline_bib(id)
419
444
  %Q([#{@chapter.bibpaper(id).number}])
420
445
  rescue KeyError
421
- error "unknown bib: #{id}"
446
+ app_error "unknown bib: #{id}"
422
447
  end
423
448
 
424
449
  def noindent
@@ -480,7 +505,7 @@ module ReVIEW
480
505
  begin
481
506
  puts "◆→画像 #{@chapter.image(id).path.sub(%r{\A\./}, '')}#{metrics}←◆"
482
507
  rescue
483
- warn "image not bound: #{id}"
508
+ warn "image not bound: #{id}", location: location
484
509
  puts "◆→画像 #{id}←◆"
485
510
  end
486
511
  if !caption_top?('image') && caption.present?
data/lib/review/update.rb CHANGED
@@ -301,6 +301,7 @@ module ReVIEW
301
301
  if !config['htmlversion'].present? || config['htmlversion'].to_f >= HTML_VERSION.to_f
302
302
  next
303
303
  end
304
+
304
305
  if confirm("%s: Update '%s' to '%s' from '%s'?", [File.basename(yml), 'htmlversion', HTML_VERSION, config['htmlversion']])
305
306
  rewrite_yml(yml, 'htmlversion', HTML_VERSION)
306
307
  end
@@ -313,6 +314,7 @@ module ReVIEW
313
314
  if !config['chapter_quote'].present? || config['chapter_quote'].scan('%s').size != 1
314
315
  next
315
316
  end
317
+
316
318
  v = config['chapter_quote'].sub('%s', '%s %s')
317
319
  if confirm("%s: 'chapter_quote' now takes 2 values. Update '%s' to '%s'?", [File.basename(yml), config['chapter_quote'], v])
318
320
  rewrite_yml(yml, 'chapter_quote', v)
@@ -414,9 +416,7 @@ module ReVIEW
414
416
  opts << "paper=#{v.sub('j', '').sub('paper', '')}"
415
417
  when /[\d.]+ptj/ # not cared...
416
418
  opts << "fontsize=#{v.sub('j', '')}"
417
- when /[\d.]+pt/
418
- opts << "fontsize=#{v}"
419
- when /[\d.]+Q/
419
+ when /[\d.]+pt/, /[\d.]+Q/
420
420
  opts << "fontsize=#{v}"
421
421
  when 'landscape', 'oneside', 'twoside', 'vartwoside', 'onecolumn',
422
422
  'twocolumn', 'titlepage', 'notitlepage', 'openright',
@@ -442,9 +442,7 @@ module ReVIEW
442
442
  opts << "paper=#{v.sub('j', '').sub('paper', '')}"
443
443
  when /[\d.]+ptj/ # not cared...
444
444
  opts << "fontsize=#{v.sub('j', '')}"
445
- when /[\d.]+pt/
446
- opts << "fontsize=#{v}"
447
- when /[\d.]+Q/
445
+ when /[\d.]+pt/, /[\d.]+Q/
448
446
  opts << "fontsize=#{v}"
449
447
  when 'landscape', 'oneside', 'twoside', 'onecolumn', 'twocolumn', 'titlepage', 'notitlepage', 'openright', 'openany', 'leqno', 'fleqn', 'draft', 'final', 'report'
450
448
  # pass-through
@@ -516,6 +514,7 @@ module ReVIEW
516
514
  if !config['texcommand'] || config['texcommand'] !~ /\s+-/
517
515
  next
518
516
  end
517
+
519
518
  # option should be moved to texoptions
520
519
  cmd, opts = config['texcommand'].split(/\s+-/, 2)
521
520
  opts = "-#{opts}"
@@ -1,3 +1,3 @@
1
1
  module ReVIEW
2
- VERSION = '5.0.0'.freeze
2
+ VERSION = '5.3.0'.freeze
3
3
  end