review 1.0.0 → 1.1.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 (100) hide show
  1. data/.travis.yml +1 -2
  2. data/ChangeLog +65 -0
  3. data/Gemfile +5 -0
  4. data/README.rdoc +6 -1
  5. data/Rakefile +14 -28
  6. data/bin/review-check +9 -21
  7. data/bin/review-compile +45 -12
  8. data/bin/review-epubmaker +477 -220
  9. data/bin/review-epubmaker-ng +5 -14
  10. data/bin/review-index +4 -2
  11. data/bin/review-init +94 -0
  12. data/bin/review-pdfmaker +70 -287
  13. data/bin/review-preproc +5 -2
  14. data/bin/review-vol +4 -11
  15. data/debian/changelog +3 -3
  16. data/debian/copyright +5 -3
  17. data/debian/docs +1 -0
  18. data/doc/format.rdoc +57 -11
  19. data/doc/quickstart.rdoc +4 -4
  20. data/doc/sample.yaml +11 -7
  21. data/lib/epubmaker.rb +1 -1
  22. data/lib/epubmaker/epubv2.rb +26 -27
  23. data/lib/epubmaker/epubv3.rb +13 -13
  24. data/lib/epubmaker/producer.rb +1 -1
  25. data/lib/review.rb +3 -4
  26. data/lib/review/book.rb +17 -581
  27. data/lib/review/book/base.rb +247 -0
  28. data/lib/review/book/chapter.rb +81 -0
  29. data/lib/review/book/compilable.rb +163 -0
  30. data/lib/review/book/index.rb +339 -0
  31. data/lib/review/book/page_metric.rb +38 -0
  32. data/lib/review/book/parameters.rb +97 -0
  33. data/lib/review/book/part.rb +44 -0
  34. data/lib/review/book/volume.rb +65 -0
  35. data/lib/review/builder.rb +34 -40
  36. data/lib/review/compiler.rb +32 -13
  37. data/lib/review/configure.rb +38 -0
  38. data/lib/review/ewbbuilder.rb +23 -21
  39. data/lib/review/extentions.rb +3 -0
  40. data/lib/review/extentions/object.rb +9 -0
  41. data/lib/review/{compat.rb → extentions/string.rb} +11 -0
  42. data/lib/review/htmlbuilder.rb +162 -74
  43. data/lib/review/htmlutils.rb +28 -1
  44. data/lib/review/i18n.yaml +11 -0
  45. data/lib/review/idgxmlbuilder.rb +119 -35
  46. data/lib/review/inaobuilder.rb +355 -0
  47. data/lib/review/latexbuilder.rb +133 -59
  48. data/lib/review/latexutils.rb +15 -6
  49. data/lib/review/makerhelper.rb +59 -0
  50. data/lib/review/markdownbuilder.rb +129 -0
  51. data/lib/review/preprocessor.rb +20 -7
  52. data/lib/review/review.tex.erb +250 -0
  53. data/lib/review/textutils.rb +28 -3
  54. data/lib/review/tocparser.rb +20 -12
  55. data/lib/review/tocprinter.rb +7 -3
  56. data/lib/review/topbuilder.rb +44 -27
  57. data/lib/review/version.rb +3 -0
  58. data/review.gemspec +20 -117
  59. data/test/book_test_helper.rb +35 -0
  60. data/test/sample-book/README.md +5 -0
  61. data/test/sample-book/src/CHAPS +2 -0
  62. data/test/sample-book/src/PREDEF +1 -0
  63. data/test/sample-book/src/Rakefile +26 -0
  64. data/test/sample-book/src/_cover.html +3 -0
  65. data/test/sample-book/src/ch01.re +71 -0
  66. data/test/sample-book/src/ch02.re +3 -0
  67. data/test/sample-book/src/config.yml +55 -0
  68. data/test/sample-book/src/images/ch01-imgsample.jpg +0 -0
  69. data/test/sample-book/src/images/cover.jpg +0 -0
  70. data/test/sample-book/src/main.css +251 -0
  71. data/test/sample-book/src/preface.re +15 -0
  72. data/test/sample-book/src/sty/jumoline.sty +310 -0
  73. data/test/sample-book/src/sty/samplemacro.sty +21 -0
  74. data/test/sample-book/src/vendor/jumoline/README +29 -0
  75. data/test/sample-book/src/vendor/jumoline/jumoline.dtx +2988 -0
  76. data/test/sample-book/src/vendor/jumoline/jumoline.ins +6 -0
  77. data/test/test_book.rb +26 -646
  78. data/test/test_book_chapter.rb +418 -0
  79. data/test/test_book_parameter.rb +42 -0
  80. data/test/test_book_part.rb +53 -0
  81. data/test/test_builder.rb +17 -10
  82. data/test/test_compiler.rb +46 -0
  83. data/test/test_epubmaker.rb +1 -1
  84. data/test/test_epubmaker_cmd.rb +36 -0
  85. data/test/test_helper.rb +17 -0
  86. data/test/test_htmlbuilder.rb +156 -24
  87. data/test/test_htmlutils.rb +4 -0
  88. data/test/test_i18n.rb +6 -2
  89. data/test/test_idgxmlbuilder.rb +33 -11
  90. data/test/test_inaobuilder.rb +247 -0
  91. data/test/test_index.rb +31 -0
  92. data/test/test_latexbuilder.rb +115 -35
  93. data/test/test_makerhelper.rb +50 -0
  94. data/test/test_pdfmaker_cmd.rb +36 -0
  95. data/test/test_preprocessor.rb +7 -7
  96. data/test/test_topbuilder.rb +6 -7
  97. data/test/test_uuid.rb +1 -0
  98. metadata +117 -12
  99. data/lib/review/index.rb +0 -323
  100. data/lib/review/volume.rb +0 -66
@@ -0,0 +1,339 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (c) 2002-2007 Minero Aoki
4
+ # 2008-2009 Minero Aoki, Kenshi Muto
5
+ #
6
+ # This program is free software.
7
+ # You can distribute or modify this program under the terms of
8
+ # the GNU LGPL, Lesser General Public License version 2.1.
9
+ # For details of LGPL, see the file "COPYING".
10
+ #
11
+
12
+ require 'review/extentions'
13
+ require 'review/exception'
14
+
15
+ module ReVIEW
16
+ module Book
17
+ class Index
18
+ def Index.parse(src, *args)
19
+ items = []
20
+ seq = 1
21
+ src.grep(%r<^//#{item_type()}>) do |line|
22
+ if id = line.slice(/\[(.*?)\]/, 1)
23
+ items.push item_class().new(id, seq)
24
+ seq += 1
25
+ if id == ""
26
+ warn "warning: no ID of #{item_type()} in #{line}"
27
+ end
28
+ end
29
+ end
30
+ new(items, *args)
31
+ end
32
+
33
+ Item = Struct.new(:id, :number)
34
+
35
+ def Index.item_class
36
+ self::Item
37
+ end
38
+
39
+ include Enumerable
40
+
41
+ def item_type
42
+ self.class.item_type
43
+ end
44
+
45
+ def initialize(items)
46
+ @items = items
47
+ @index = {}
48
+ items.each do |i|
49
+ warn "warning: duplicate ID: #{i.id} (#{i})" unless @index[i.id].nil?
50
+ @index[i.id] = i
51
+ end
52
+ end
53
+
54
+ def [](id)
55
+ @index.fetch(id)
56
+ rescue
57
+ raise KeyError
58
+ end
59
+
60
+ def number(id)
61
+ @index.fetch(id).number.to_s
62
+ end
63
+
64
+ def each(&block)
65
+ @items.each(&block)
66
+ end
67
+
68
+ def has_key?(id)
69
+ return @index.has_key?(id)
70
+ end
71
+ end
72
+
73
+
74
+ class ChapterIndex < Index
75
+ def item_type
76
+ 'chapter'
77
+ end
78
+
79
+ def number(id)
80
+ 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
88
+ end
89
+
90
+ def title(id)
91
+ @index.fetch(id).title
92
+ end
93
+
94
+ def display_string(id)
95
+ "#{number(id)}「#{title(id)}」"
96
+ end
97
+ end
98
+
99
+
100
+ class ListIndex < Index
101
+ def ListIndex.item_type
102
+ '(list|listnum)'
103
+ end
104
+ end
105
+
106
+
107
+ class TableIndex < Index
108
+ def TableIndex.item_type
109
+ 'table'
110
+ end
111
+ end
112
+
113
+
114
+ class FootnoteIndex < Index
115
+ Item = Struct.new(:id, :number, :content)
116
+
117
+ def FootnoteIndex.parse(src)
118
+ items = []
119
+ seq = 1
120
+ src.grep(%r<^//footnote>) do |line|
121
+ if m = /\[(.*?)\]\[(.*)\]/.match(line)
122
+ m1 = m[1].gsub(/\\(\])/){$1}
123
+ m2 = m[2].gsub(/\\(\])/){$1}
124
+ items.push Item.new(m1, seq, m2)
125
+ end
126
+ seq += 1
127
+ end
128
+ new(items)
129
+ end
130
+ end
131
+
132
+
133
+ class ImageIndex < Index
134
+ class Item
135
+ def initialize(id, number)
136
+ @id = id
137
+ @number = number
138
+ @pathes = nil
139
+ end
140
+
141
+ attr_reader :id
142
+ attr_reader :number
143
+ attr_writer :index # internal use only
144
+
145
+ def bound?
146
+ not pathes().empty?
147
+ end
148
+
149
+ def path
150
+ pathes().first
151
+ end
152
+
153
+ def pathes
154
+ @pathes ||= @index.find_pathes(id)
155
+ end
156
+ end
157
+
158
+ def ImageIndex.item_type
159
+ '(image|graph)'
160
+ end
161
+
162
+ def initialize(items, chapid, basedir, types)
163
+ super items
164
+ items.each do |i|
165
+ i.index = self
166
+ end
167
+ @chapid = chapid
168
+ @basedir = basedir
169
+ @types = types
170
+ end
171
+
172
+ # internal use only
173
+ def find_pathes(id)
174
+ if ReVIEW.book.param["subdirmode"]
175
+ re = /\A#{id}(?i:#{@types.join('|')})\z/x
176
+ entries().select {|ent| re =~ ent }\
177
+ .sort_by {|ent| @types.index(File.extname(ent).downcase) }\
178
+ .map {|ent| "#{@basedir}/#{@chapid}/#{ent}" }
179
+ elsif ReVIEW.book.param["singledirmode"]
180
+ re = /\A#{id}(?i:#{@types.join('|')})\z/x
181
+ entries().select {|ent| re =~ ent }\
182
+ .sort_by {|ent| @types.index(File.extname(ent).downcase) }\
183
+ .map {|ent| "#{@basedir}/#{ent}" }
184
+ else
185
+ re = /\A#{@chapid.gsub('+', '\\\+').gsub('-', '\\\-')}-#{id}(?i:#{@types.join('|')})\z/x
186
+ entries().select {|ent| re =~ ent }\
187
+ .sort_by {|ent| @types.index(File.extname(ent).downcase) }\
188
+ .map {|ent| "#{@basedir}/#{ent}" }
189
+ end
190
+ end
191
+
192
+ private
193
+
194
+ def entries
195
+ # @entries: do not cache for graph
196
+ if ReVIEW.book.param["subdirmode"]
197
+ @entries = Dir.entries(File.join(@basedir, @chapid))
198
+ else
199
+ @entries = Dir.entries(@basedir)
200
+ end
201
+ rescue Errno::ENOENT
202
+ @entries = []
203
+ end
204
+ end
205
+
206
+ class IconIndex < ImageIndex
207
+ def IconIndex.parse(src, *args)
208
+ items = []
209
+ seq = 1
210
+ src.grep(%r!@<icon>!) do |line|
211
+ line.gsub(/@<icon>\{(.+?)\}/) do |m|
212
+ items.push item_class().new($1, seq)
213
+ seq += 1
214
+ end
215
+ end
216
+ new(items, *args)
217
+ end
218
+ end
219
+
220
+ class FormatRef
221
+ def initialize(locale, index)
222
+ @locale = locale
223
+ @index = index
224
+ end
225
+
226
+ def title(id)
227
+ sprintf(@locale["#{@index.item_type}_caption_format".intern],
228
+ @index.title(id))
229
+ end
230
+
231
+ def number(id)
232
+ sprintf(@locale["#{@index.item_type}_number_format".intern],
233
+ @index.number(id))
234
+ end
235
+
236
+ def method_missing(mid, *args, &block)
237
+ super unless @index.respond_to?(mid)
238
+ @index.__send__(mid, *args, &block)
239
+ end
240
+ end
241
+
242
+ class BibpaperIndex < Index
243
+ Item = Struct.new(:id, :number, :caption)
244
+
245
+ def BibpaperIndex.parse(src)
246
+ items = []
247
+ seq = 1
248
+ src.grep(%r<^//bibpaper>) do |line|
249
+ if m = /\[(.*?)\]\[(.*)\]/.match(line)
250
+ m1 = m[1].gsub(/\\(.)/){$1}
251
+ m2 = m[2].gsub(/\\(.)/){$1}
252
+ items.push Item.new(m1, seq, m2)
253
+ end
254
+ seq += 1
255
+ end
256
+ new(items)
257
+ end
258
+ end
259
+
260
+ class NumberlessImageIndex < ImageIndex
261
+ class Item < ImageIndex::Item
262
+ def initialize(id, number)
263
+ @id = id
264
+ @number = ""
265
+ @pathes = nil
266
+ end
267
+ end
268
+
269
+ def NumberlessImageIndex.item_type
270
+ 'numberlessimage'
271
+ end
272
+
273
+ def number(id)
274
+ ""
275
+ end
276
+ end
277
+
278
+ class IndepImageIndex < ImageIndex
279
+ class Item < ImageIndex::Item
280
+ def initialize(id, number)
281
+ @id = id
282
+ @number = ""
283
+ @pathes = nil
284
+ end
285
+ end
286
+
287
+ def IndepImageIndex.item_type
288
+ 'indepimage'
289
+ end
290
+
291
+ def number(id)
292
+ ""
293
+ end
294
+ end
295
+
296
+ class HeadlineIndex < Index
297
+ Item = Struct.new(:id, :number, :caption)
298
+
299
+ def HeadlineIndex.parse(src, chap)
300
+ items = []
301
+ indexs = []
302
+ headlines = []
303
+ src.each do |line|
304
+ if m = /\A(=+)(?:\[(.+?)\])?(?:\{(.+?)\})?(.*)/.match(line)
305
+ next if m[2] == 'column'
306
+ index = m[1].size - 2
307
+ if index >= 0
308
+ if indexs.size > (index + 1)
309
+ indexs = indexs.take(index + 1)
310
+ headlines = headlines.take(index + 1)
311
+ end
312
+ if indexs[index].nil?
313
+ (0..index).each{|i| indexs[i] = 0 if indexs[i].nil?}
314
+ end
315
+ indexs[index] += 1
316
+ headlines[index] = m[3].present? ? m[3].strip : m[4].strip
317
+ items.push Item.new(headlines.join("|"), indexs.dup, m[4].strip)
318
+ end
319
+ end
320
+ end
321
+ new(items, chap)
322
+ end
323
+
324
+ def initialize(items, chap)
325
+ @items = items
326
+ @chap = chap
327
+ @index = {}
328
+ items.each do |i|
329
+ warn "warning: duplicate ID: #{i.id}" unless @index[i.id].nil?
330
+ @index[i.id] = i
331
+ end
332
+ end
333
+
334
+ def number(id)
335
+ return ([@chap.number] + @index.fetch(id).number).join(".")
336
+ end
337
+ end
338
+ end
339
+ end
@@ -0,0 +1,38 @@
1
+ #
2
+ # $Id: book.rb 4315 2009-09-02 04:15:24Z kmuto $
3
+ #
4
+ # Copyright (c) 2002-2008 Minero Aoki
5
+ # 2009 Minero Aoki, Kenshi Muto
6
+ #
7
+ # This program is free software.
8
+ # You can distribute or modify this program under the terms of
9
+ # the GNU LGPL, Lesser General Public License version 2.1.
10
+ # For details of the GNU LGPL, see the file "COPYING".
11
+ #
12
+ module ReVIEW
13
+ module Book
14
+ class PageMetric
15
+
16
+ MetricData = Struct.new(:n_lines, :n_columns)
17
+
18
+ def PageMetric.a5
19
+ new(46, 80, 30, 74, 1)
20
+ end
21
+
22
+ def PageMetric.b5
23
+ new(46, 80, 30, 74, 2)
24
+ end
25
+
26
+ def initialize(list_lines, list_columns, text_lines, text_columns, page_per_kbyte)
27
+ @list = MetricData.new(list_lines, list_columns)
28
+ @text = MetricData.new(text_lines, text_columns)
29
+ @page_per_kbyte = page_per_kbyte
30
+ end
31
+
32
+ attr_reader :list
33
+ attr_reader :text
34
+ attr_reader :page_per_kbyte
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,97 @@
1
+ #
2
+ # $Id: book.rb 4315 2009-09-02 04:15:24Z kmuto $
3
+ #
4
+ # Copyright (c) 2002-2008 Minero Aoki
5
+ # 2009 Minero Aoki, Kenshi Muto
6
+ #
7
+ # This program is free software.
8
+ # You can distribute or modify this program under the terms of
9
+ # the GNU LGPL, Lesser General Public License version 2.1.
10
+ # For details of the GNU LGPL, see the file "COPYING".
11
+ #
12
+ module ReVIEW
13
+ module Book
14
+ class Parameters
15
+
16
+ def Parameters.default
17
+ new()
18
+ end
19
+
20
+ def Parameters.load(path)
21
+ mod = Module.new
22
+ mod.module_eval File.read(path), path
23
+ new(
24
+ :chapter_file => const_get_safe(mod, :CHAPS_FILE),
25
+ :part_file => const_get_safe(mod, :PART_FILE),
26
+ :bib_file => const_get_safe(mod, :BIB_FILE),
27
+ :reject_file => const_get_safe(mod, :REJECT_FILE) ||
28
+ const_get_safe(mod, :WORDS_FILE),
29
+ :predef_file => const_get_safe(mod, :PREDEF_FILE),
30
+ :postdef_file => const_get_safe(mod, :POSTDEF_FILE),
31
+ :ext => const_get_safe(mod, :EXT),
32
+ :image_dir => const_get_safe(mod, :IMAGE_DIR),
33
+ :image_types => const_get_safe(mod, :IMAGE_TYPES),
34
+ :page_metric => get_page_metric(mod)
35
+ )
36
+ end
37
+
38
+ def Parameters.get_page_metric(mod)
39
+ if paper = const_get_safe(mod, :PAPER)
40
+ unless PageMetric.respond_to?(paper.downcase)
41
+ raise ConfigError, "unknown paper size: #{paper}"
42
+ end
43
+ return PageMetric.send(paper.downcase)
44
+ end
45
+ PageMetric.new(const_get_safe(mod, :LINES_PER_PAGE_list) || 46,
46
+ const_get_safe(mod, :COLUMNS_list) || 80,
47
+ const_get_safe(mod, :LINES_PER_PAGE_text) || 30,
48
+ const_get_safe(mod, :COLUMNS_text) || 74) # 37zw
49
+ end
50
+
51
+ def Parameters.const_get_safe(mod, name)
52
+ return nil unless mod.const_defined?(name)
53
+ mod.const_get(name)
54
+ end
55
+ private_class_method :const_get_safe
56
+
57
+ def initialize(params = {})
58
+ @chapter_file = params[:chapter_file] || 'CHAPS'
59
+ @part_file = params[:part_file] || 'PART'
60
+ @reject_file = params[:reject_file] || 'REJECT'
61
+ @predef_file = params[:predef_file] || 'PREDEF'
62
+ @postdef_file = params[:postdef_file] || 'POSTDEF'
63
+ @page_metric = params[:page_metric] || PageMetric.a5
64
+ @ext = params[:ext] || '.re'
65
+ @image_dir = params[:image_dir] || 'images'
66
+ @image_types = unify_exts(params[:image_types] ||
67
+ %w( ai psd eps pdf tif tiff png bmp jpg jpeg gif svg ))
68
+ @bib_file = params[:bib_file] || "bib#{@ext}"
69
+ end
70
+
71
+ def unify_exts(list)
72
+ list.map {|ext| (ext[0] == '.') ? ext : ".#{ext}" }
73
+ end
74
+ private :unify_exts
75
+
76
+ def self.path_param(name)
77
+ module_eval(<<-End, __FILE__, __LINE__ + 1)
78
+ def #{name}
79
+ "\#{@basedir}/\#{@#{name}}"
80
+ end
81
+ End
82
+ end
83
+
84
+ path_param :chapter_file
85
+ path_param :part_file
86
+ path_param :bib_file
87
+ path_param :reject_file
88
+ path_param :predef_file
89
+ path_param :postdef_file
90
+ attr_reader :ext
91
+ path_param :image_dir
92
+ attr_reader :image_types
93
+ attr_reader :page_metric
94
+
95
+ end
96
+ end
97
+ end