review 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +36 -0
  3. data/.rubocop.yml +1 -0
  4. data/ChangeLog +102 -0
  5. data/README.rdoc +2 -2
  6. data/bin/review-check +18 -16
  7. data/bin/review-compile +49 -42
  8. data/bin/review-epubmaker +23 -993
  9. data/bin/review-epubmaker-legacy +1024 -0
  10. data/bin/review-index +17 -15
  11. data/bin/review-init +39 -9
  12. data/bin/review-pdfmaker +124 -89
  13. data/bin/review-preproc +16 -14
  14. data/bin/review-vol +17 -15
  15. data/debian/docs +1 -1
  16. data/doc/catalog.rdoc +34 -0
  17. data/doc/format.rdoc +16 -2
  18. data/doc/libepubmaker/{config.yaml → config.yml} +63 -19
  19. data/doc/quickstart.rdoc +1 -1
  20. data/doc/{sample.yaml → sample.yml} +0 -0
  21. data/lib/epubmaker.rb +1 -1
  22. data/lib/epubmaker/content.rb +9 -1
  23. data/lib/epubmaker/epubv2.rb +59 -7
  24. data/lib/epubmaker/epubv3.rb +14 -9
  25. data/lib/epubmaker/producer.rb +68 -27
  26. data/lib/epubmaker/resource.rb +3 -1
  27. data/lib/lineinput.rb +2 -2
  28. data/lib/review/book/base.rb +125 -24
  29. data/lib/review/book/chapter.rb +42 -0
  30. data/lib/review/book/compilable.rb +23 -4
  31. data/lib/review/book/image_finder.rb +64 -0
  32. data/lib/review/book/index.rb +64 -50
  33. data/lib/review/book/page_metric.rb +1 -1
  34. data/lib/review/builder.rb +19 -12
  35. data/lib/review/catalog.rb +47 -0
  36. data/lib/review/compiler.rb +3 -2
  37. data/lib/review/configure.rb +5 -3
  38. data/lib/review/epubmaker.rb +130 -46
  39. data/lib/review/ewbbuilder.rb +27 -31
  40. data/lib/review/extentions/string.rb +4 -4
  41. data/lib/review/htmlbuilder.rb +140 -79
  42. data/lib/review/htmllayout.rb +26 -4
  43. data/lib/review/htmlutils.rb +20 -1
  44. data/lib/review/i18n.rb +5 -2
  45. data/lib/review/{i18n.yaml → i18n.yml} +4 -2
  46. data/lib/review/idgxmlbuilder.rb +65 -39
  47. data/lib/review/latexbuilder.rb +72 -24
  48. data/lib/review/latexutils.rb +3 -1
  49. data/lib/review/makerhelper.rb +8 -2
  50. data/lib/review/preprocessor.rb +20 -20
  51. data/lib/review/review.tex.erb +4 -0
  52. data/lib/review/sec_counter.rb +9 -11
  53. data/lib/review/tocparser.rb +2 -2
  54. data/lib/review/tocprinter.rb +12 -12
  55. data/lib/review/topbuilder.rb +15 -15
  56. data/lib/review/version.rb +1 -1
  57. data/lib/uuid.rb +7 -7
  58. data/review.gemspec +2 -2
  59. data/rubocop-todo.yml +443 -0
  60. data/test/sample-book/src/config.yml +2 -2
  61. data/test/sample-book/src/{main.css → style.css} +0 -0
  62. data/test/test_book.rb +46 -48
  63. data/test/test_book_chapter.rb +25 -13
  64. data/test/test_builder.rb +3 -3
  65. data/test/test_catalog.rb +107 -0
  66. data/test/test_epubmaker.rb +6 -6
  67. data/test/test_htmlbuilder.rb +160 -39
  68. data/test/test_htmlutils.rb +22 -0
  69. data/test/test_i18n.rb +2 -2
  70. data/test/test_idgxmlbuilder.rb +33 -47
  71. data/test/test_image_finder.rb +82 -0
  72. data/test/test_inaobuilder.rb +1 -1
  73. data/test/test_latexbuilder.rb +35 -39
  74. data/test/test_lineinput.rb +2 -2
  75. data/test/test_markdownbuilder.rb +2 -2
  76. data/test/test_topbuilder.rb +39 -23
  77. metadata +23 -14
  78. data/bin/review-epubmaker-ng +0 -23
@@ -15,6 +15,9 @@ module ReVIEW
15
15
  class Chapter
16
16
  include Compilable
17
17
 
18
+ ROMAN = %w[0 I II III IV V VI VII VIII IX X XI XII XIII XIV XV XVI XVII XVIII XIX XX XXI XXII XXIII XXIV XXV XXVI XXVII]
19
+ ALPHA = %w[0 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z]
20
+
18
21
  def Chapter.intern_pathes(pathes)
19
22
  books = {}
20
23
  pathes.map {|path|
@@ -54,12 +57,51 @@ module ReVIEW
54
57
  @numberless_image_index = nil
55
58
  @indepimage_index = nil
56
59
  @headline_index = nil
60
+ @column_index = nil
57
61
  end
58
62
 
59
63
  def inspect
60
64
  "\#<#{self.class} #{@number} #{@path}>"
61
65
  end
62
66
 
67
+ def format_number(heading = true)
68
+ if on_PREDEF?
69
+ return "#{@number}"
70
+ end
71
+
72
+ if on_POSTDEF?
73
+ return "#{@number}" if @number < 1 || @number > 27
74
+
75
+ if @book.config["appendix_format"].blank?
76
+ type = "arabic"
77
+ else
78
+ type = @book.config["appendix_format"].downcase.strip
79
+ end
80
+
81
+ appendix = case type
82
+ when "roman"
83
+ ROMAN[@number]
84
+ when "alphabet", "alpha"
85
+ ALPHA[@number]
86
+ else
87
+ # nil, "arabic", etc...
88
+ "#{@number}"
89
+ end
90
+
91
+ if heading
92
+ return "#{I18n.t("appendix", appendix)}"
93
+ else
94
+ return "#{appendix}"
95
+ end
96
+ end
97
+
98
+ if heading
99
+ "#{I18n.t("chapter", @number)}"
100
+ else
101
+ "#{@number}"
102
+ end
103
+ end
104
+
63
105
  def on_CHAPS?
64
106
  on_FILE?(@book.read_CHAPS())
65
107
  end
@@ -32,16 +32,19 @@ module ReVIEW
32
32
  end
33
33
 
34
34
  def name
35
+ return nil unless @name
35
36
  File.basename(@name, '.*')
36
37
  end
37
38
 
38
- alias id name
39
+ alias_method :id, :name
39
40
 
40
41
  def title
41
- @title = ""
42
+ return @title if @title
43
+
44
+ @title = ''
42
45
  open {|f|
43
46
  f.each_line {|l|
44
- l = convert_inencoding(l, ReVIEW.book.param["inencoding"])
47
+ l = convert_inencoding(l, book.config["inencoding"])
45
48
  if l =~ /\A=+/
46
49
  @title = l.sub(/\A=+(\[.+?\])?(\{.+?\})?/, '').strip
47
50
  break
@@ -68,7 +71,7 @@ module ReVIEW
68
71
 
69
72
  def content
70
73
  @content = convert_inencoding(File.read(path()),
71
- ReVIEW.book.param["inencoding"])
74
+ book.config["inencoding"])
72
75
  rescue
73
76
  @content
74
77
  end
@@ -157,6 +160,22 @@ module ReVIEW
157
160
  def headline_index
158
161
  @headline_index ||= HeadlineIndex.parse(lines(), self)
159
162
  end
163
+
164
+ def column(id)
165
+ column_index()[id]
166
+ end
167
+
168
+ def column_index
169
+ @column_index ||= ColumnIndex.parse(lines())
170
+ end
171
+
172
+ def next_chapter
173
+ book.next_chapter(self)
174
+ end
175
+
176
+ def prev_chapter
177
+ book.prev_chapter(self)
178
+ end
160
179
  end
161
180
  end
162
181
  end
@@ -0,0 +1,64 @@
1
+ #
2
+ # Copyright (c) 2014 Minero Aoki, Kenshi Muto, Masayoshi Takahashi
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 LGPL, see the file "COPYING".
8
+ #
9
+
10
+ require 'review/extentions'
11
+ require 'review/exception'
12
+
13
+ module ReVIEW
14
+ module Book
15
+ class ImageFinder
16
+ def initialize(basedir, chapid, builder, exts)
17
+ @basedir = basedir
18
+ @chapid = chapid
19
+ @builder = builder
20
+ @exts = exts
21
+ @entries = get_entries()
22
+ end
23
+
24
+ def get_entries
25
+ Dir.glob(File.join(@basedir, "**/*.*"))
26
+ end
27
+
28
+ def find_path(id)
29
+ targets = target_list(id)
30
+ targets.each do |target|
31
+ @exts.each do |ext|
32
+ if @entries.include?("#{target}#{ext}")
33
+ return "#{target}#{ext}"
34
+ end
35
+ end
36
+ end
37
+ nil
38
+ end
39
+
40
+ def target_list(id)
41
+ [
42
+ # 1. <basedir>/<builder>/<chapid>/<id>.<ext>
43
+ "#{@basedir}/#{@builder}/#{@chapid}/#{id}",
44
+
45
+ # 2. <basedir>/<builder>/<chapid>-<id>.<ext>
46
+ "#{@basedir}/#{@builder}/#{@chapid}-#{id}",
47
+
48
+ # 3. <basedir>/<builder>/<id>.<ext>
49
+ "#{@basedir}/#{@builder}/#{id}",
50
+
51
+ # 4. <basedir>/<chapid>/<id>.<ext>
52
+ "#{@basedir}/#{@chapid}/#{id}",
53
+
54
+ # 5. <basedir>/<chapid>-<id>.<ext>
55
+ "#{@basedir}/#{@chapid}-#{id}",
56
+
57
+ # 6. <basedir>/<id>.<ext>
58
+ "#{@basedir}/#{id}"
59
+ ]
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -11,6 +11,7 @@
11
11
 
12
12
  require 'review/extentions'
13
13
  require 'review/exception'
14
+ require 'review/book/image_finder'
14
15
 
15
16
  module ReVIEW
16
17
  module Book
@@ -49,12 +50,13 @@ module ReVIEW
49
50
  warn "warning: duplicate ID: #{i.id} (#{i})" unless @index[i.id].nil?
50
51
  @index[i.id] = i
51
52
  end
53
+ @image_finder = nil
52
54
  end
53
55
 
54
56
  def [](id)
55
57
  @index.fetch(id)
56
58
  rescue
57
- raise KeyError
59
+ raise KeyError, "not found key '#{id}' for #{self.class}"
58
60
  end
59
61
 
60
62
  def number(id)
@@ -78,17 +80,15 @@ module ReVIEW
78
80
 
79
81
  def number(id)
80
82
  chapter = @index.fetch(id)
81
- if chapter.on_CHAPS?
82
- "#{I18n.t("chapter", chapter.number)}"
83
- elsif chapter.on_PREDEF?
84
- "#{chapter.number}"
85
- elsif chapter.on_POSTDEF?
86
- "#{I18n.t("appendix", chapter.number)}"
87
- end
83
+ chapter.format_number
84
+ rescue # part
85
+ "#{I18n.t("part", chapter.number)}"
88
86
  end
89
87
 
90
88
  def title(id)
91
89
  @index.fetch(id).title
90
+ rescue # non-file part
91
+ @index.fetch(id).name
92
92
  end
93
93
 
94
94
  def display_string(id)
@@ -132,12 +132,11 @@ module ReVIEW
132
132
 
133
133
  class ImageIndex < Index
134
134
  class Item
135
- @@entries = nil
136
135
 
137
136
  def initialize(id, number)
138
137
  @id = id
139
138
  @number = number
140
- @pathes = nil
139
+ @path = nil
141
140
  end
142
141
 
143
142
  attr_reader :id
@@ -145,22 +144,21 @@ module ReVIEW
145
144
  attr_writer :index # internal use only
146
145
 
147
146
  def bound?
148
- not pathes().empty?
147
+ path
149
148
  end
150
149
 
151
150
  def path
152
- pathes().first
151
+ @path ||= @index.find_path(id)
153
152
  end
154
153
 
155
- def pathes
156
- @pathes ||= @index.find_pathes(id)
157
- end
158
154
  end
159
155
 
160
156
  def ImageIndex.item_type
161
157
  '(image|graph)'
162
158
  end
163
159
 
160
+ attr_reader :image_finder
161
+
164
162
  def initialize(items, chapid, basedir, types)
165
163
  super items
166
164
  items.each do |i|
@@ -170,46 +168,34 @@ module ReVIEW
170
168
  @basedir = basedir
171
169
  @types = types
172
170
 
173
- @@entries ||= get_entries
171
+ @image_finder = ReVIEW::Book::ImageFinder.new(basedir, chapid,
172
+ ReVIEW.book.config['builder'], types)
174
173
  end
175
174
 
176
- def get_entries
177
- Dir.glob(File.join(@basedir, "**/*.*"))
175
+ def find_path(id)
176
+ @image_finder.find_path(id)
178
177
  end
179
178
 
180
- # internal use only
181
- def find_pathes(id)
182
- pathes = []
183
-
184
- # 1. <basedir>/<builder>/<chapid>/<id>.<ext>
185
- target = "#{@basedir}/#{ReVIEW.book.param['builder']}/#{@chapid}/#{id}"
186
- @types.each {|ext| pathes.push("#{target}#{ext}") if @@entries.include?("#{target}#{ext}")}
187
-
188
- # 2. <basedir>/<builder>/<chapid>-<id>.<ext>
189
- target = "#{@basedir}/#{ReVIEW.book.param['builder']}/#{@chapid}-#{id}"
190
- @types.each {|ext| pathes.push("#{target}#{ext}") if @@entries.include?("#{target}#{ext}")}
191
-
192
- # 3. <basedir>/<builder>/<id>.<ext>
193
- target = "#{@basedir}/#{ReVIEW.book.param['builder']}/#{id}"
194
- @types.each {|ext| pathes.push("#{target}#{ext}") if @@entries.include?("#{target}#{ext}")}
195
-
196
- # 4. <basedir>/<chapid>/<id>.<ext>
197
- target = "#{@basedir}/#{@chapid}/#{id}"
198
- @types.each {|ext| pathes.push("#{target}#{ext}") if @@entries.include?("#{target}#{ext}")}
199
-
200
- # 5. <basedir>/<chapid>-<id>.<ext>
201
- target = "#{@basedir}/#{@chapid}-#{id}"
202
- @types.each {|ext| pathes.push("#{target}#{ext}") if @@entries.include?("#{target}#{ext}")}
179
+ end
203
180
 
204
- # 6. <basedir>/<id>.<ext>
205
- target = "#{@basedir}/#{id}"
206
- @types.each {|ext| pathes.push("#{target}#{ext}") if @@entries.include?("#{target}#{ext}")}
181
+ class IconIndex < ImageIndex
182
+ def initialize(items, chapid, basedir, types)
183
+ @items = items
184
+ @index = {}
185
+ items.each do |i|
186
+ ## warn "warning: duplicate ID: #{i.id} (#{i})" unless @index[i.id].nil?
187
+ @index[i.id] = i
188
+ end
189
+ items.each do |i|
190
+ i.index = self
191
+ end
192
+ @chapid = chapid
193
+ @basedir = basedir
194
+ @types = types
207
195
 
208
- return pathes
196
+ @image_finder = ImageFinder.new(basedir, chapid, ReVIEW.book.config['builder'], types)
209
197
  end
210
- end
211
198
 
212
- class IconIndex < ImageIndex
213
199
  def IconIndex.parse(src, *args)
214
200
  items = []
215
201
  seq = 1
@@ -268,7 +254,7 @@ module ReVIEW
268
254
  def initialize(id, number)
269
255
  @id = id
270
256
  @number = ""
271
- @pathes = nil
257
+ @path = nil
272
258
  end
273
259
  end
274
260
 
@@ -286,7 +272,7 @@ module ReVIEW
286
272
  def initialize(id, number)
287
273
  @id = id
288
274
  @number = ""
289
- @pathes = nil
275
+ @path = nil
290
276
  end
291
277
  end
292
278
 
@@ -300,14 +286,16 @@ module ReVIEW
300
286
  end
301
287
 
302
288
  class HeadlineIndex < Index
289
+ HEADLINE_PATTERN = /\A(=+)(?:\[(.+?)\])?(?:\{(.+?)\})?(.*)/
303
290
  Item = Struct.new(:id, :number, :caption)
291
+ attr_reader :items
304
292
 
305
293
  def HeadlineIndex.parse(src, chap)
306
294
  items = []
307
295
  indexs = []
308
296
  headlines = []
309
297
  src.each do |line|
310
- if m = /\A(=+)(?:\[(.+?)\])?(?:\{(.+?)\})?(.*)/.match(line)
298
+ if m = HEADLINE_PATTERN.match(line)
311
299
  next if m[2] == 'column'
312
300
  index = m[1].size - 2
313
301
  if index >= 0
@@ -341,5 +329,31 @@ module ReVIEW
341
329
  return ([@chap.number] + @index.fetch(id).number).join(".")
342
330
  end
343
331
  end
332
+
333
+ class ColumnIndex < Index
334
+ COLUMN_PATTERN = /\A(=+)\[column\](?:\{(.+?)\})?(.*)/
335
+ Item = Struct.new(:id, :number, :caption)
336
+
337
+ def ColumnIndex.parse(src, *args)
338
+ items = []
339
+ seq = 1
340
+ src.each do |line|
341
+ if m = COLUMN_PATTERN.match(line)
342
+ level = m[1] ## not use it yet
343
+ id = m[2]
344
+ caption = m[3].strip
345
+ if !id || id == ""
346
+ id = caption
347
+ end
348
+
349
+ items.push item_class().new(id, seq, caption)
350
+ seq += 1
351
+ end
352
+ end
353
+ new(items)
354
+ end
355
+
356
+ end
357
+
344
358
  end
345
359
  end
@@ -22,7 +22,7 @@ module ReVIEW
22
22
  def PageMetric.b5
23
23
  new(46, 80, 30, 74, 2)
24
24
  end
25
-
25
+
26
26
  def initialize(list_lines, list_columns, text_lines, text_columns, page_per_kbyte)
27
27
  @list = MetricData.new(list_lines, list_columns)
28
28
  @text = MetricData.new(text_lines, text_columns)
@@ -30,10 +30,6 @@ module ReVIEW
30
30
 
31
31
  def initialize(strict = false, *args)
32
32
  @strict = strict
33
- @tabwidth = nil
34
- if ReVIEW.book.param && ReVIEW.book.param["tabwidth"]
35
- @tabwidth = ReVIEW.book.param["tabwidth"]
36
- end
37
33
  builder_init(*args)
38
34
  end
39
35
 
@@ -47,6 +43,10 @@ module ReVIEW
47
43
  @location = location
48
44
  @output = StringIO.new
49
45
  @book = ReVIEW.book
46
+ @tabwidth = nil
47
+ if @book.config && @book.config["tabwidth"]
48
+ @tabwidth = @book.config["tabwidth"]
49
+ end
50
50
  builder_init_file
51
51
  end
52
52
 
@@ -58,17 +58,17 @@ module ReVIEW
58
58
  @output.string
59
59
  end
60
60
 
61
- alias :raw_result result
61
+ alias_method :raw_result, :result
62
62
 
63
63
  def print(*s)
64
64
  @output.print(*s.map{|i|
65
- convert_outencoding(i, ReVIEW.book.param["outencoding"])
65
+ convert_outencoding(i, @book.config["outencoding"])
66
66
  })
67
67
  end
68
68
 
69
69
  def puts(*s)
70
70
  @output.puts *s.map{|i|
71
- convert_outencoding(i, ReVIEW.book.param["outencoding"])
71
+ convert_outencoding(i, @book.config["outencoding"])
72
72
  }
73
73
  end
74
74
 
@@ -257,12 +257,19 @@ module ReVIEW
257
257
  end
258
258
 
259
259
  def inline_hd(id)
260
- m = /\A(\w+)\|(.+)/.match(id)
260
+ m = /\A([^|]+)\|(.+)/.match(id)
261
261
  chapter = @book.chapters.detect{|chap| chap.id == m[1]} if m && m[1]
262
262
  return inline_hd_chap(chapter, m[2]) if chapter
263
263
  return inline_hd_chap(@chapter, id)
264
264
  end
265
265
 
266
+ def inline_column(id)
267
+ @chapter.column(id).caption
268
+ rescue
269
+ error "unknown column: #{id}"
270
+ nofunc_text("[UnknownColumn:#{id}]")
271
+ end
272
+
266
273
  def raw(str)
267
274
  if matched = str.match(/\|(.*?)\|(.*)/)
268
275
  builders = matched[1].split(/,/).map{|i| i.gsub(/\s/, '') }
@@ -312,7 +319,7 @@ module ReVIEW
312
319
  end
313
320
 
314
321
  def get_chap(chapter = @chapter)
315
- if ReVIEW.book.param["secnolevel"] > 0 && !chapter.number.nil? && !chapter.number.to_s.empty?
322
+ if @book.config["secnolevel"] > 0 && !chapter.number.nil? && !chapter.number.to_s.empty?
316
323
  return "#{chapter.number}"
317
324
  end
318
325
  return nil
@@ -346,7 +353,7 @@ module ReVIEW
346
353
  file = "#{id}.#{image_ext}"
347
354
  file_path = File.join(dir, file)
348
355
 
349
- line = CGI.unescapeHTML(lines.join("\n"))
356
+ line = self.unescape(lines.join("\n"))
350
357
  cmds = {
351
358
  :graphviz => "echo '#{line}' | dot -T#{image_ext} -o#{file_path}",
352
359
  :gnuplot => "echo 'set terminal " +
@@ -369,12 +376,12 @@ module ReVIEW
369
376
 
370
377
  def inline_include(file_name)
371
378
  compile_inline convert_inencoding(File.open(file_name).read,
372
- ReVIEW.book.param["inencoding"])
379
+ @book.config["inencoding"])
373
380
  end
374
381
 
375
382
  def include(file_name)
376
383
  File.foreach(file_name) do |line|
377
- paragraph([convert_inencoding(line, ReVIEW.book.param["inencoding"])])
384
+ paragraph([convert_inencoding(line, @book.config["inencoding"])])
378
385
  end
379
386
  end
380
387