review 4.0.0 → 5.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (268) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-tex.yml +31 -0
  3. data/.github/workflows/ruby-win.yml +45 -0
  4. data/.github/workflows/ruby.yml +27 -0
  5. data/.rubocop.yml +141 -38
  6. data/Dockerfile +21 -5
  7. data/NEWS.ja.md +338 -1
  8. data/NEWS.md +339 -2
  9. data/README.md +11 -7
  10. data/Rakefile +7 -2
  11. data/appveyor.yml +0 -20
  12. data/bin/review +2 -4
  13. data/bin/review-catalog-converter +4 -4
  14. data/bin/review-check +8 -12
  15. data/bin/review-checkdep +2 -5
  16. data/bin/review-compile +11 -20
  17. data/bin/review-epub2html +1 -4
  18. data/bin/review-epubmaker +3 -4
  19. data/bin/review-idgxmlmaker +1 -3
  20. data/bin/review-index +5 -86
  21. data/bin/review-init +1 -4
  22. data/bin/review-pdfmaker +1 -3
  23. data/bin/review-preproc +3 -5
  24. data/bin/review-textmaker +1 -3
  25. data/bin/review-update +1 -4
  26. data/bin/review-validate +5 -5
  27. data/bin/review-vol +5 -82
  28. data/bin/review-webmaker +1 -3
  29. data/doc/config.yml.sample +55 -12
  30. data/doc/config.yml.sample-simple +4 -3
  31. data/doc/format.ja.md +119 -17
  32. data/doc/format.md +106 -17
  33. data/doc/makeindex.ja.md +2 -2
  34. data/doc/pdfmaker.ja.md +42 -0
  35. data/doc/pdfmaker.md +41 -0
  36. data/doc/quickstart.ja.md +55 -25
  37. data/doc/quickstart.md +47 -17
  38. data/lib/review.rb +1 -1
  39. data/lib/review/book.rb +2 -2
  40. data/lib/review/book/base.rb +69 -30
  41. data/lib/review/book/bib.rb +21 -0
  42. data/lib/review/book/book_unit.rb +158 -0
  43. data/lib/review/book/chapter.rb +33 -26
  44. data/lib/review/book/index.rb +39 -206
  45. data/lib/review/book/index/item.rb +8 -2
  46. data/lib/review/book/page_metric.rb +7 -7
  47. data/lib/review/book/part.rb +26 -11
  48. data/lib/review/book/volume.rb +5 -5
  49. data/lib/review/builder.rb +124 -27
  50. data/lib/review/call_hook.rb +20 -0
  51. data/lib/review/catalog.rb +3 -2
  52. data/lib/review/compiler.rb +197 -91
  53. data/lib/review/configure.rb +95 -9
  54. data/lib/review/converter.rb +1 -1
  55. data/lib/review/epub2html.rb +6 -1
  56. data/lib/review/epubmaker.rb +116 -117
  57. data/lib/review/epubmaker/content.rb +113 -0
  58. data/lib/review/epubmaker/epubcommon.rb +372 -0
  59. data/lib/review/epubmaker/epubv2.rb +178 -0
  60. data/lib/review/epubmaker/epubv3.rb +231 -0
  61. data/lib/review/epubmaker/producer.rb +168 -0
  62. data/lib/review/epubmaker/reviewheaderlistener.rb +12 -2
  63. data/lib/review/epubmaker/zip_exporter.rb +84 -0
  64. data/lib/review/exception.rb +6 -0
  65. data/lib/review/extentions/string.rb +0 -4
  66. data/lib/review/htmlbuilder.rb +132 -87
  67. data/lib/review/htmlutils.rb +8 -11
  68. data/lib/review/i18n.rb +2 -1
  69. data/lib/review/idgxmlbuilder.rb +156 -76
  70. data/lib/review/idgxmlmaker.rb +22 -18
  71. data/lib/review/img_math.rb +245 -0
  72. data/lib/review/index_builder.rb +654 -0
  73. data/lib/review/init.rb +17 -18
  74. data/lib/review/latexbox.rb +58 -0
  75. data/lib/review/latexbuilder.rb +173 -43
  76. data/lib/review/latexutils.rb +9 -1
  77. data/lib/review/lineinput.rb +112 -2
  78. data/lib/review/logger.rb +42 -3
  79. data/lib/review/makerhelper.rb +12 -187
  80. data/lib/review/markdownbuilder.rb +51 -2
  81. data/lib/review/pdfmaker.rb +78 -73
  82. data/lib/review/plaintextbuilder.rb +98 -14
  83. data/lib/review/preprocessor.rb +18 -12
  84. data/lib/review/rstbuilder.rb +28 -9
  85. data/lib/review/sec_counter.rb +14 -0
  86. data/lib/review/template.rb +6 -0
  87. data/lib/review/textmaker.rb +21 -19
  88. data/lib/review/textutils.rb +3 -12
  89. data/lib/review/tocprinter.rb +242 -97
  90. data/lib/review/topbuilder.rb +91 -24
  91. data/lib/review/update.rb +12 -13
  92. data/lib/review/version.rb +1 -1
  93. data/lib/review/volumeprinter.rb +97 -0
  94. data/lib/review/webmaker.rb +34 -33
  95. data/lib/review/webtocprinter.rb +39 -35
  96. data/lib/review/yamlloader.rb +2 -1
  97. data/review.gemspec +5 -3
  98. data/samples/sample-book/src/.gitignore +1 -0
  99. data/samples/sample-book/src/config-ebook.yml +4 -0
  100. data/samples/sample-book/src/config-epub2.yml +1 -1
  101. data/samples/sample-book/src/config-jlreq-ebook.yml +4 -0
  102. data/samples/sample-book/src/config.yml +3 -3
  103. data/samples/sample-book/src/lib/tasks/review.rake +26 -6
  104. data/samples/syntax-book/Gemfile +1 -1
  105. data/samples/syntax-book/ch01.re +3 -1
  106. data/samples/syntax-book/ch02.re +28 -21
  107. data/samples/syntax-book/ch03.re +1 -1
  108. data/samples/syntax-book/config-jlreq-lualatex.yml +4 -0
  109. data/samples/syntax-book/config-print.yml +3 -0
  110. data/samples/syntax-book/config.yml +1 -1
  111. data/samples/syntax-book/images/img3-2.png +0 -0
  112. data/samples/syntax-book/lib/tasks/review.rake +23 -8
  113. data/templates/html/_colophon.html.erb +23 -0
  114. data/templates/html/_colophon_history.html.erb +9 -0
  115. data/templates/html/_cover.html.erb +10 -0
  116. data/templates/html/_part_body.html.erb +6 -0
  117. data/templates/html/_titlepage.html.erb +20 -0
  118. data/templates/html/layout-html5.html.erb +6 -0
  119. data/templates/html/layout-xhtml1.html.erb +6 -0
  120. data/templates/latex/config.erb +41 -29
  121. data/templates/latex/review-jlreq/README.md +3 -1
  122. data/templates/latex/review-jlreq/review-base.sty +47 -22
  123. data/templates/latex/review-jlreq/review-jlreq.cls +25 -24
  124. data/templates/latex/review-jlreq/review-style.sty +6 -1
  125. data/templates/latex/review-jlreq/review-tcbox.sty +348 -0
  126. data/templates/latex/review-jlreq/reviewmacro.sty +5 -0
  127. data/templates/latex/review-jsbook/README.md +7 -5
  128. data/templates/latex/review-jsbook/review-base.sty +47 -21
  129. data/templates/latex/review-jsbook/review-jsbook.cls +12 -2
  130. data/templates/latex/review-jsbook/review-style.sty +6 -1
  131. data/templates/latex/review-jsbook/review-tcbox.sty +348 -0
  132. data/templates/latex/review-jsbook/reviewmacro.sty +5 -0
  133. data/templates/opf/epubv2.opf.erb +7 -7
  134. data/templates/opf/epubv3.opf.erb +7 -7
  135. data/templates/opf/opf_manifest_epubv2.opf.erb +10 -0
  136. data/templates/opf/opf_manifest_epubv3.opf.erb +10 -0
  137. data/templates/opf/opf_metainfo_epubv2.opf.erb +17 -0
  138. data/templates/opf/opf_metainfo_epubv3.opf.erb +49 -0
  139. data/templates/opf/opf_tocx_epubv2.opf.erb +9 -0
  140. data/templates/opf/opf_tocx_epubv3.opf.erb +17 -0
  141. data/templates/web/html/layout-html5.html.erb +9 -8
  142. data/templates/web/html/layout-xhtml1.html.erb +6 -0
  143. data/test/assets/header_listener.html +35 -0
  144. data/test/assets/img_math/img1.png +0 -0
  145. data/test/assets/img_math/img2.png +0 -0
  146. data/test/assets/img_math/img3.png +0 -0
  147. data/test/assets/syntax_book_index_detail.txt +58 -0
  148. data/test/assets/test_template.tex +12 -9
  149. data/test/assets/test_template_backmatter.tex +12 -9
  150. data/test/book_test_helper.rb +11 -5
  151. data/test/run_test.rb +1 -1
  152. data/test/test_book.rb +62 -63
  153. data/test/test_book_chapter.rb +99 -56
  154. data/test/test_book_part.rb +3 -3
  155. data/test/test_builder.rb +24 -15
  156. data/test/test_catalog.rb +1 -0
  157. data/test/test_catalog_converter_cmd.rb +1 -1
  158. data/test/test_converter.rb +1 -0
  159. data/test/test_epub3maker.rb +170 -126
  160. data/test/test_epubmaker.rb +249 -129
  161. data/test/test_epubmaker_cmd.rb +14 -7
  162. data/test/test_helper.rb +23 -11
  163. data/test/test_htmlbuilder.rb +956 -76
  164. data/test/test_htmlutils.rb +0 -12
  165. data/test/test_i18n.rb +33 -33
  166. data/test/test_idgxmlbuilder.rb +568 -10
  167. data/test/test_idgxmlmaker_cmd.rb +50 -0
  168. data/test/test_image_finder.rb +52 -70
  169. data/test/test_img_math.rb +111 -0
  170. data/test/test_index.rb +62 -52
  171. data/test/test_indexbuilder.rb +52 -0
  172. data/test/test_latexbuilder.rb +1056 -30
  173. data/test/test_latexbuilder_v2.rb +52 -12
  174. data/test/test_lineinput.rb +20 -93
  175. data/test/test_logger.rb +7 -7
  176. data/test/test_makerhelper.rb +0 -12
  177. data/test/test_markdownbuilder.rb +32 -0
  178. data/test/test_pdfmaker.rb +100 -11
  179. data/test/test_pdfmaker_cmd.rb +101 -7
  180. data/test/test_plaintextbuilder.rb +531 -25
  181. data/test/test_review_ext.rb +2 -1
  182. data/test/test_reviewheaderlistener.rb +49 -0
  183. data/test/test_rstbuilder.rb +25 -1
  184. data/test/test_sec_counter.rb +156 -0
  185. data/test/test_template.rb +12 -2
  186. data/test/test_textmaker_cmd.rb +58 -0
  187. data/test/test_tocprinter.rb +46 -0
  188. data/test/test_topbuilder.rb +365 -10
  189. data/test/test_update.rb +44 -44
  190. data/test/test_webtocprinter.rb +75 -43
  191. data/test/test_zip_exporter.rb +5 -6
  192. data/vendor/gentombow/LICENSE +1 -1
  193. data/vendor/gentombow/Makefile +0 -1
  194. data/vendor/gentombow/bounddvi-en.pdf +0 -0
  195. data/vendor/gentombow/bounddvi-en.tex +1 -0
  196. data/vendor/gentombow/bounddvi.pdf +0 -0
  197. data/vendor/gentombow/bounddvi.sty +30 -7
  198. data/vendor/gentombow/bounddvi.tex +1 -0
  199. data/vendor/gentombow/create_archive.sh +1 -0
  200. data/vendor/gentombow/gentombow-ja.pdf +0 -0
  201. data/vendor/gentombow/gentombow-ja.tex +9 -0
  202. data/vendor/gentombow/gentombow.pdf +0 -0
  203. data/vendor/gentombow/gentombow.sty +32 -10
  204. data/vendor/gentombow/gentombow.tex +8 -0
  205. data/vendor/gentombow/tests/gentombow-01-pdfx.tex +8 -0
  206. data/vendor/gentombow/tests/gentombow-02-pdfx.tex +8 -0
  207. data/vendor/jsclasses/LICENSE +1 -1
  208. data/vendor/jsclasses/Makefile +3 -2
  209. data/vendor/jsclasses/create_archive.sh +5 -5
  210. data/vendor/jsclasses/jis/Makefile +3 -2
  211. data/vendor/jsclasses/jis/jsarticle.cls +74 -31
  212. data/vendor/jsclasses/jis/jsbook.cls +74 -31
  213. data/vendor/jsclasses/jis/jsclasses.dtx +176 -36
  214. data/vendor/jsclasses/jis/jsclasses.ins +15 -5
  215. data/vendor/jsclasses/jis/jslogo.dtx +4 -4
  216. data/vendor/jsclasses/jis/jslogo.ins +9 -0
  217. data/vendor/jsclasses/jis/jslogo.sty +4 -16
  218. data/vendor/jsclasses/jis/jspf.cls +73 -30
  219. data/vendor/jsclasses/jis/jsreport.cls +74 -31
  220. data/vendor/jsclasses/jis/jsverb.ins +9 -0
  221. data/vendor/jsclasses/jis/jsverb.sty +1 -13
  222. data/vendor/jsclasses/jis/kiyou.cls +74 -31
  223. data/vendor/jsclasses/jis/minijs.sty +65 -22
  224. data/vendor/jsclasses/jis/okumacro.dtx +4 -5
  225. data/vendor/jsclasses/jis/okumacro.ins +9 -0
  226. data/vendor/jsclasses/jis/okumacro.sty +4 -17
  227. data/vendor/jsclasses/jis/okuverb.ins +9 -0
  228. data/vendor/jsclasses/jis/okuverb.sty +1 -13
  229. data/vendor/jsclasses/jis/winjis.sty +23 -19
  230. data/vendor/jsclasses/jsarticle.cls +74 -31
  231. data/vendor/jsclasses/jsbook.cls +74 -31
  232. data/vendor/jsclasses/jsclasses.dtx +176 -36
  233. data/vendor/jsclasses/jsclasses.ins +15 -5
  234. data/vendor/jsclasses/jsclasses.pdf +0 -0
  235. data/vendor/jsclasses/jslogo.dtx +4 -4
  236. data/vendor/jsclasses/jslogo.ins +9 -0
  237. data/vendor/jsclasses/jslogo.pdf +0 -0
  238. data/vendor/jsclasses/jslogo.sty +4 -16
  239. data/vendor/jsclasses/jspf.cls +73 -30
  240. data/vendor/jsclasses/jsreport.cls +74 -31
  241. data/vendor/jsclasses/jsverb.ins +9 -0
  242. data/vendor/jsclasses/jsverb.pdf +0 -0
  243. data/vendor/jsclasses/jsverb.sty +1 -13
  244. data/vendor/jsclasses/kiyou.cls +74 -31
  245. data/vendor/jsclasses/minijs.sty +68 -22
  246. data/vendor/jsclasses/okumacro.dtx +4 -5
  247. data/vendor/jsclasses/okumacro.ins +9 -0
  248. data/vendor/jsclasses/okumacro.pdf +0 -0
  249. data/vendor/jsclasses/okumacro.sty +4 -17
  250. data/vendor/jsclasses/okuverb.ins +9 -0
  251. data/vendor/jsclasses/okuverb.pdf +0 -0
  252. data/vendor/jsclasses/okuverb.sty +1 -13
  253. data/vendor/jsclasses/tests/relfont.tex +10 -0
  254. data/vendor/jsclasses/winjis.sty +23 -19
  255. metadata +109 -20
  256. data/.rubocop_todo.yml +0 -7
  257. data/lib/epubmaker.rb +0 -23
  258. data/lib/epubmaker/content.rb +0 -110
  259. data/lib/epubmaker/epubcommon.rb +0 -441
  260. data/lib/epubmaker/epubv2.rb +0 -143
  261. data/lib/epubmaker/epubv3.rb +0 -233
  262. data/lib/epubmaker/producer.rb +0 -375
  263. data/lib/epubmaker/zip_exporter.rb +0 -81
  264. data/lib/lineinput.rb +0 -155
  265. data/lib/review/book/compilable.rb +0 -178
  266. data/lib/review/tocparser.rb +0 -271
  267. data/samples/syntax-book/review-ext.rb +0 -14
  268. data/test/test_tocparser.rb +0 -25
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2009-2019 Minero Aoki, Kenshi Muto
1
+ # Copyright (c) 2009-2020 Minero Aoki, Kenshi Muto, Masayoshi Takahashi
2
2
  # 2002-2008 Minero Aoki
3
3
  #
4
4
  # This program is free software.
@@ -6,13 +6,11 @@
6
6
  # the GNU LGPL, Lesser General Public License version 2.1.
7
7
  # For details of the GNU LGPL, see the file "COPYING".
8
8
  #
9
- require 'review/book/compilable'
9
+ require 'review/book/book_unit'
10
10
 
11
11
  module ReVIEW
12
12
  module Book
13
- class Part
14
- include Compilable
15
-
13
+ class Part < BookUnit
16
14
  def self.mkpart_from_namelistfile(book, path)
17
15
  chaps = []
18
16
  File.read(path, mode: 'rt:BOM|utf-8').split.each_with_index do |name, number|
@@ -30,7 +28,7 @@ module ReVIEW
30
28
  end
31
29
 
32
30
  def self.mkpart(chaps)
33
- chaps.empty? ? nil : Part.new(self, nil, chaps)
31
+ chaps.empty? ? nil : Part.new(chaps[0].book, nil, chaps)
34
32
  end
35
33
 
36
34
  # if Part is dummy, `number` is nil.
@@ -38,15 +36,16 @@ module ReVIEW
38
36
  def initialize(book, number, chapters, name = '', io = nil)
39
37
  @book = book
40
38
  @number = number
41
- @chapters = chapters
42
39
  @name = name
40
+ @chapters = chapters
43
41
  @path = name
44
- @content = nil
45
42
  if io
46
43
  @content = io.read
47
44
  elsif @path.present? && File.exist?(File.join(@book.config['contentdir'], @path))
48
45
  @content = File.read(File.join(@book.config['contentdir'], @path), mode: 'rt:BOM|utf-8')
49
- @name = File.basename(@name, '.re')
46
+ @name = File.basename(name, '.re')
47
+ else
48
+ @content = ''
50
49
  end
51
50
  if file?
52
51
  @title = nil
@@ -54,6 +53,19 @@ module ReVIEW
54
53
  @title = name
55
54
  end
56
55
  @volume = nil
56
+
57
+ super()
58
+ end
59
+
60
+ def generate_indexes
61
+ super
62
+
63
+ return unless content
64
+
65
+ @numberless_image_index = @indexes.numberless_image_index
66
+ @image_index = @indexes.image_index
67
+ @icon_index = @indexes.icon_index
68
+ @indepimage_index = @indexes.indepimage_index
57
69
  end
58
70
 
59
71
  attr_reader :number
@@ -65,8 +77,11 @@ module ReVIEW
65
77
  end
66
78
 
67
79
  def volume
68
- vol = Volume.sum(@chapters.map(&:volume))
69
- vol.page_per_kbyte = @book.page_metric.page_per_kbyte
80
+ if @number && file?
81
+ vol = Volume.count_file(File.join(@book.config['contentdir'], @path))
82
+ else
83
+ vol = Volume.new(0, 0, 0)
84
+ end
70
85
  vol
71
86
  end
72
87
 
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2017 Minero Aoki, Kenshi Muto
1
+ # Copyright (c) 2007-2020 Minero Aoki, Kenshi Muto
2
2
  # 2002-2007 Minero Aoki
3
3
  #
4
4
  # This program is free software.
@@ -13,6 +13,7 @@ module ReVIEW
13
13
  b = c = l = 0
14
14
  File.foreach(path) do |line|
15
15
  next if /\A\#@/ =~ line
16
+
16
17
  text = line.gsub(/\s+/, '')
17
18
  b += text.bytesize
18
19
  c += text.size
@@ -22,7 +23,7 @@ module ReVIEW
22
23
  end
23
24
 
24
25
  def self.sum(vols)
25
- vols.inject(new) { |sum, i| sum + i }
26
+ vols.inject(new) { |sum, i| sum + i } # rubocop:disable Performance/Sum
26
27
  end
27
28
 
28
29
  def self.dummy
@@ -33,20 +34,19 @@ module ReVIEW
33
34
  @bytes = bytes
34
35
  @chars = chars
35
36
  @lines = lines
36
- @page_per_kbyte = nil
37
37
  end
38
38
 
39
39
  attr_reader :bytes
40
40
  attr_reader :chars
41
41
  attr_accessor :lines
42
- attr_accessor :page_per_kbyte
43
42
 
44
43
  def kbytes
45
44
  (@bytes.to_f / 1024).ceil
46
45
  end
47
46
 
48
47
  def page
49
- (kbytes.to_f / @page_per_kbyte).ceil
48
+ # XXX:unrelibable
49
+ kbytes.to_f.ceil
50
50
  end
51
51
 
52
52
  def to_s
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2002-2019 Minero Aoki, Kenshi Muto
1
+ # Copyright (c) 2002-2020 Minero Aoki, Kenshi Muto
2
2
  #
3
3
  # This program is free software.
4
4
  # You can distribute or modify this program under the terms of
@@ -10,8 +10,8 @@ require 'review/exception'
10
10
  require 'review/textutils'
11
11
  require 'review/compiler'
12
12
  require 'review/sec_counter'
13
+ require 'review/img_math'
13
14
  require 'stringio'
14
- require 'cgi'
15
15
  require 'fileutils'
16
16
  require 'tempfile'
17
17
  require 'csv'
@@ -20,7 +20,7 @@ module ReVIEW
20
20
  class Builder
21
21
  include TextUtils
22
22
 
23
- CAPTION_TITLES = %w[note memo tip info warning important caution notice].freeze
23
+ CAPTION_TITLES = Compiler.minicolumn_names
24
24
 
25
25
  def pre_paragraph
26
26
  nil
@@ -30,21 +30,18 @@ module ReVIEW
30
30
  nil
31
31
  end
32
32
 
33
- attr_accessor :doc_status
33
+ attr_accessor :doc_status, :previous_list_type
34
34
 
35
- def initialize(strict = false, *args)
35
+ def initialize(strict = false, *_args, img_math: nil)
36
36
  @strict = strict
37
37
  @output = nil
38
38
  @logger = ReVIEW.logger
39
39
  @doc_status = {}
40
40
  @dictionary = {}
41
- builder_init(*args)
41
+ @previous_list_type = nil
42
+ @img_math = img_math
42
43
  end
43
44
 
44
- def builder_init(*args)
45
- end
46
- private :builder_init
47
-
48
45
  def bind(compiler, chapter, location)
49
46
  @compiler = compiler
50
47
  @chapter = chapter
@@ -53,11 +50,23 @@ module ReVIEW
53
50
  if @chapter.present?
54
51
  @book = @chapter.book
55
52
  end
53
+ @chapter.generate_indexes
54
+ if @book
55
+ @book.generate_indexes
56
+ end
56
57
  @tabwidth = nil
57
58
  @tsize = nil
58
59
  if @book && @book.config
59
- if @book.config['words_file']
60
- load_words(@book.config['words_file'])
60
+ @img_math ||= ReVIEW::ImgMath.new(@book.config)
61
+ if words_file_path = @book.config['words_file']
62
+ if words_file_path.is_a?(String)
63
+ words_files = [words_file_path]
64
+ else
65
+ words_files = words_file_path
66
+ end
67
+ words_files.each do |f|
68
+ load_words(f)
69
+ end
61
70
  end
62
71
  if @book.config['tabwidth']
63
72
  @tabwidth = @book.config['tabwidth']
@@ -77,6 +86,7 @@ module ReVIEW
77
86
 
78
87
  def builder_init_file
79
88
  @sec_counter = SecCounter.new(5, @chapter)
89
+ @doc_status = {}
80
90
  end
81
91
  private :builder_init_file
82
92
 
@@ -84,8 +94,19 @@ module ReVIEW
84
94
  false
85
95
  end
86
96
 
97
+ def solve_nest(s)
98
+ check_nest
99
+ s.gsub(/\x01→.+?←\x01/, '')
100
+ end
101
+
102
+ def check_nest
103
+ if @children && !@children.empty?
104
+ error "//beginchild of #{@children.reverse.join(',')} misses //endchild"
105
+ end
106
+ end
107
+
87
108
  def result
88
- @output.string
109
+ solve_nest(@output.string)
89
110
  end
90
111
 
91
112
  alias_method :raw_result, :result
@@ -127,6 +148,7 @@ module ReVIEW
127
148
 
128
149
  def line_num
129
150
  return 1 unless @first_line_num
151
+
130
152
  line_n = @first_line_num
131
153
  @first_line_num = nil
132
154
 
@@ -135,25 +157,28 @@ module ReVIEW
135
157
 
136
158
  def list(lines, id, caption, lang = nil)
137
159
  begin
138
- list_header(id, caption, lang)
160
+ list_header(id, caption, lang) if caption_top?('list')
161
+ list_body(id, lines, lang)
162
+ list_header(id, caption, lang) unless caption_top?('list')
139
163
  rescue KeyError
140
164
  error "no such list: #{id}"
141
165
  end
142
- list_body(id, lines, lang)
143
166
  end
144
167
 
145
168
  def listnum(lines, id, caption, lang = nil)
146
169
  begin
147
- list_header(id, caption, lang)
170
+ list_header(id, caption, lang) if caption_top?('list')
171
+ listnum_body(lines, lang)
172
+ list_header(id, caption, lang) unless caption_top?('list')
148
173
  rescue KeyError
149
174
  error "no such list: #{id}"
150
175
  end
151
- listnum_body(lines, lang)
152
176
  end
153
177
 
154
- def source(lines, caption, lang = nil)
155
- source_header(caption)
178
+ def source(lines, caption = nil, lang = nil)
179
+ source_header(caption) if caption_top?('list')
156
180
  source_body(lines, lang)
181
+ source_header(caption) unless caption_top?('list')
157
182
  end
158
183
 
159
184
  def image(lines, id, caption, metric = nil)
@@ -168,26 +193,44 @@ module ReVIEW
168
193
  def table(lines, id = nil, caption = nil)
169
194
  sepidx, rows = parse_table_rows(lines)
170
195
  begin
171
- if caption.present?
196
+ if caption_top?('table') && caption.present?
197
+ table_header(id, caption)
198
+ end
199
+ table_begin(rows.first.size)
200
+ table_rows(sepidx, rows)
201
+ table_end
202
+ if !caption_top?('table') && caption.present?
172
203
  table_header(id, caption)
173
204
  end
174
205
  rescue KeyError
175
206
  error "no such table: #{id}"
176
207
  end
177
- table_begin(rows.first.size)
178
- table_rows(sepidx, rows)
179
- table_end
208
+ end
209
+
210
+ def table_row_separator_regexp
211
+ case @book.config['table_row_separator']
212
+ when 'tabs'
213
+ Regexp.new('\t+')
214
+ when 'singletab'
215
+ Regexp.new('\t')
216
+ when 'spaces'
217
+ Regexp.new('\s+')
218
+ when 'verticalbar'
219
+ Regexp.new('\s*\\' + escape('|') + '\s*')
220
+ else
221
+ error "Unknown value for 'table_row_separator', shold be: tabs, singletab, spaces, verticalbar"
222
+ end
180
223
  end
181
224
 
182
225
  def parse_table_rows(lines)
183
226
  sepidx = nil
184
227
  rows = []
185
228
  lines.each_with_index do |line, idx|
186
- if /\A[\=\-]{12}/ =~ line || /\A[\=\{\-\}]{12}/ =~ line
229
+ if /\A[=\-]{12}/ =~ line || /\A[={\-}]{12}/ =~ line
187
230
  sepidx ||= idx
188
231
  next
189
232
  end
190
- rows.push(line.strip.split(/\t+/).map { |s| s.sub(/\A\./, '') })
233
+ rows.push(line.strip.split(table_row_separator_regexp).map { |s| s.sub(/\A\./, '') })
191
234
  end
192
235
  rows = adjust_n_cols(rows)
193
236
  error 'no rows in the table' if rows.empty?
@@ -212,7 +255,7 @@ module ReVIEW
212
255
 
213
256
  def adjust_n_cols(rows)
214
257
  rows.each do |cols|
215
- while cols.last and cols.last.strip.empty?
258
+ while cols.last && cols.last.strip.empty?
216
259
  cols.pop
217
260
  end
218
261
  end
@@ -475,11 +518,13 @@ module ReVIEW
475
518
 
476
519
  def parse_metric(type, metric)
477
520
  return '' if metric.blank?
521
+
478
522
  params = metric.split(/,\s*/)
479
523
  results = []
480
524
  params.each do |param|
481
525
  if param =~ /\A.+?::/
482
526
  next unless param =~ /\A#{type}::/
527
+
483
528
  param.sub!(/\A#{type}::/, '')
484
529
  end
485
530
  param2 = handle_metric(param)
@@ -504,6 +549,7 @@ module ReVIEW
504
549
  if m
505
550
  ch = @book.contents.detect { |chap| chap.id == m[1] }
506
551
  raise KeyError unless ch
552
+
507
553
  return [ch, m[2]]
508
554
  end
509
555
  [@chapter, chap_ref]
@@ -516,9 +562,36 @@ module ReVIEW
516
562
  CAPTION_TITLES.each do |name|
517
563
  class_eval %Q(
518
564
  def #{name}(lines, caption = nil)
565
+ check_nested_minicolumn
519
566
  captionblock("#{name}", lines, caption)
520
567
  end
521
- )
568
+
569
+ def #{name}_begin(caption = nil)
570
+ check_nested_minicolumn
571
+ @doc_status[:minicolumn] = '#{name}'
572
+ if caption
573
+ puts compile_inline(caption)
574
+ end
575
+ end
576
+
577
+ def #{name}_end
578
+ @doc_status[:minicolumn] = nil
579
+ end
580
+ ), __FILE__, __LINE__ - 17
581
+ end
582
+
583
+ def check_nested_minicolumn
584
+ if @doc_status[:minicolumn]
585
+ error "#{@location}: nested mini-column is not allowed"
586
+ end
587
+ end
588
+
589
+ def in_minicolumn?
590
+ @doc_status[:minicolumn]
591
+ end
592
+
593
+ def minicolumn_block_name?(name)
594
+ CAPTION_TITLES.include?(name)
522
595
  end
523
596
 
524
597
  def graph(lines, id, command, caption = '')
@@ -658,5 +731,29 @@ EOTGNUPLOT
658
731
  def escape(str)
659
732
  str
660
733
  end
734
+
735
+ def beginchild
736
+ @children ||= []
737
+ unless @previous_list_type
738
+ error "//beginchild is shown, but previous element isn't ul, ol, or dl"
739
+ end
740
+ puts "\x01→#{@previous_list_type}←\x01"
741
+ @children.push(@previous_list_type)
742
+ end
743
+
744
+ def endchild
745
+ if @children.nil? || @children.empty?
746
+ error "//endchild is shown, but any opened //beginchild doesn't exist"
747
+ else
748
+ puts "\x01→/#{@children.pop}←\x01"
749
+ end
750
+ end
751
+
752
+ def caption_top?(type)
753
+ unless %w[top bottom].include?(@book.config['caption_position'][type])
754
+ warn("invalid caption_position/#{type} parameter. 'top' is assumed")
755
+ end
756
+ @book.config['caption_position'][type] != 'bottom'
757
+ end
661
758
  end
662
759
  end # module ReVIEW
@@ -0,0 +1,20 @@
1
+ module ReVIEW
2
+ module CallHook
3
+ def call_hook(hook_name, *params, base_dir: nil)
4
+ maker = @config.maker
5
+ filename = @config.dig(maker, hook_name)
6
+ return unless filename
7
+
8
+ hook = File.absolute_path(filename, base_dir)
9
+ @logger.debug("Call #{hook_name}. (#{hook})")
10
+
11
+ return if !File.exist?(hook) || !FileTest.executable?(hook)
12
+
13
+ if ENV['REVIEW_SAFE_MODE'].to_i & 1 > 0
14
+ warn 'hook configuration is prohibited in safe mode. ignored.'
15
+ else
16
+ system(hook, *params)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -41,7 +41,7 @@ module ReVIEW
41
41
 
42
42
  def replace_part(old_name, new_name)
43
43
  @yaml['CHAPS'].map! do |e|
44
- if e.is_a?(Hash) and (e.keys.first == old_name)
44
+ if e.is_a?(Hash) && (e.keys.first == old_name)
45
45
  e = { new_name => e.values.first }
46
46
  end
47
47
  e
@@ -50,6 +50,7 @@ module ReVIEW
50
50
 
51
51
  def parts_with_chaps
52
52
  return [] unless @yaml['CHAPS']
53
+
53
54
  @yaml['CHAPS'].flatten.compact
54
55
  end
55
56
 
@@ -89,7 +90,7 @@ module ReVIEW
89
90
  filenames.concat(postdef)
90
91
  end
91
92
  filenames.each do |filename|
92
- refile = File.join(basedir, config['contentdir'], filename)
93
+ refile = File.expand_path(File.join(config['contentdir'], filename), basedir)
93
94
  unless File.exist?(refile)
94
95
  raise FileNotFound, "file not found in catalog.yml: #{refile}"
95
96
  end