review-peg 0.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 (174) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/.rubocop.yml +47 -0
  4. data/.rubocop_todo.yml +605 -0
  5. data/.travis.yml +18 -0
  6. data/COPYING +515 -0
  7. data/ChangeLog +2449 -0
  8. data/Dockerfile +22 -0
  9. data/Gemfile +6 -0
  10. data/README.rdoc +81 -0
  11. data/Rakefile +51 -0
  12. data/bin/review-catalog-converter-peg +129 -0
  13. data/bin/review-check-peg +169 -0
  14. data/bin/review-checkdep-peg +63 -0
  15. data/bin/review-compile-peg +202 -0
  16. data/bin/review-epubmaker-legacy-peg +1024 -0
  17. data/bin/review-epubmaker-peg +44 -0
  18. data/bin/review-index-peg +110 -0
  19. data/bin/review-init-peg +151 -0
  20. data/bin/review-pdfmaker-peg +18 -0
  21. data/bin/review-preproc-peg +131 -0
  22. data/bin/review-validate-peg +51 -0
  23. data/bin/review-vol-peg +100 -0
  24. data/debian/README.Debian +12 -0
  25. data/debian/README.source +5 -0
  26. data/debian/changelog +5 -0
  27. data/debian/compat +1 -0
  28. data/debian/control +22 -0
  29. data/debian/copyright +62 -0
  30. data/debian/docs +6 -0
  31. data/debian/manpage.1.ex +59 -0
  32. data/debian/patches/path.diff +91 -0
  33. data/debian/patches/series +1 -0
  34. data/debian/review.install +13 -0
  35. data/debian/review.links +4 -0
  36. data/debian/rules +13 -0
  37. data/debian/source/format +1 -0
  38. data/doc/NEWS.ja.md +350 -0
  39. data/doc/NEWS.md +354 -0
  40. data/doc/catalog.ja.md +53 -0
  41. data/doc/catalog.md +52 -0
  42. data/doc/format.ja.md +734 -0
  43. data/doc/format.md +746 -0
  44. data/doc/format_idg.ja.md +203 -0
  45. data/doc/quickstart.ja.md +222 -0
  46. data/doc/quickstart.md +252 -0
  47. data/doc/ruby-uuid/README +11 -0
  48. data/doc/ruby-uuid/README.ja +34 -0
  49. data/doc/sample.css +108 -0
  50. data/doc/sample.yml +238 -0
  51. data/lib/epubmaker.rb +24 -0
  52. data/lib/epubmaker/content.rb +93 -0
  53. data/lib/epubmaker/epubcommon.rb +424 -0
  54. data/lib/epubmaker/epubv2.rb +139 -0
  55. data/lib/epubmaker/epubv3.rb +222 -0
  56. data/lib/epubmaker/producer.rb +330 -0
  57. data/lib/lineinput.rb +107 -0
  58. data/lib/review.rb +3 -0
  59. data/lib/review/book.rb +43 -0
  60. data/lib/review/book/base.rb +401 -0
  61. data/lib/review/book/chapter.rb +100 -0
  62. data/lib/review/book/compilable.rb +184 -0
  63. data/lib/review/book/image_finder.rb +71 -0
  64. data/lib/review/book/index.rb +413 -0
  65. data/lib/review/book/page_metric.rb +47 -0
  66. data/lib/review/book/part.rb +54 -0
  67. data/lib/review/book/volume.rb +67 -0
  68. data/lib/review/builder.rb +452 -0
  69. data/lib/review/catalog.rb +52 -0
  70. data/lib/review/compiler.rb +5183 -0
  71. data/lib/review/compiler/literals_1_9.kpeg +22 -0
  72. data/lib/review/compiler/literals_1_9.rb +435 -0
  73. data/lib/review/configure.rb +64 -0
  74. data/lib/review/epubbuilder.rb +18 -0
  75. data/lib/review/epubmaker.rb +480 -0
  76. data/lib/review/ewbbuilder.rb +381 -0
  77. data/lib/review/exception.rb +21 -0
  78. data/lib/review/extentions.rb +4 -0
  79. data/lib/review/extentions/array.rb +25 -0
  80. data/lib/review/extentions/object.rb +9 -0
  81. data/lib/review/extentions/string.rb +33 -0
  82. data/lib/review/htmlbuilder.rb +1166 -0
  83. data/lib/review/htmllayout.rb +41 -0
  84. data/lib/review/htmltoc.rb +45 -0
  85. data/lib/review/htmlutils.rb +90 -0
  86. data/lib/review/i18n.rb +96 -0
  87. data/lib/review/i18n.yml +169 -0
  88. data/lib/review/idgxmlbuilder.rb +1233 -0
  89. data/lib/review/inaobuilder.rb +357 -0
  90. data/lib/review/latexbuilder.rb +941 -0
  91. data/lib/review/latexindex.rb +35 -0
  92. data/lib/review/latexutils.rb +95 -0
  93. data/lib/review/layout.tex.erb +340 -0
  94. data/lib/review/lineinput.rb +17 -0
  95. data/lib/review/location.rb +24 -0
  96. data/lib/review/makerhelper.rb +67 -0
  97. data/lib/review/markdownbuilder.rb +339 -0
  98. data/lib/review/node.rb +288 -0
  99. data/lib/review/pdfmaker.rb +332 -0
  100. data/lib/review/preprocessor.rb +530 -0
  101. data/lib/review/review.kpeg +745 -0
  102. data/lib/review/sec_counter.rb +69 -0
  103. data/lib/review/template.rb +21 -0
  104. data/lib/review/textbuilder.rb +17 -0
  105. data/lib/review/textutils.rb +16 -0
  106. data/lib/review/tocparser.rb +348 -0
  107. data/lib/review/tocprinter.rb +205 -0
  108. data/lib/review/topbuilder.rb +796 -0
  109. data/lib/review/unfold.rb +138 -0
  110. data/lib/review/version.rb +3 -0
  111. data/lib/uuid.rb +312 -0
  112. data/review.gemspec +32 -0
  113. data/templates/html/layout-html5.html.erb +17 -0
  114. data/templates/html/layout-xhtml1.html.erb +20 -0
  115. data/templates/ncx/epubv2.ncx.erb +11 -0
  116. data/templates/opf/epubv2.opf.erb +21 -0
  117. data/templates/opf/epubv3.opf.erb +18 -0
  118. data/templates/xml/container.xml.erb +6 -0
  119. data/test/CHAPS +2 -0
  120. data/test/assets/test.xml.erb +3 -0
  121. data/test/assets/test_template.tex +255 -0
  122. data/test/assets/test_template_backmatter.tex +32 -0
  123. data/test/bib.re +13 -0
  124. data/test/book_test_helper.rb +35 -0
  125. data/test/sample-book/README.md +7 -0
  126. data/test/sample-book/src/Rakefile +58 -0
  127. data/test/sample-book/src/_cover.html +3 -0
  128. data/test/sample-book/src/catalog.yml +10 -0
  129. data/test/sample-book/src/ch01.re +71 -0
  130. data/test/sample-book/src/ch02.re +3 -0
  131. data/test/sample-book/src/config.yml +186 -0
  132. data/test/sample-book/src/images/ch01-imgsample.jpg +0 -0
  133. data/test/sample-book/src/images/cover.jpg +0 -0
  134. data/test/sample-book/src/preface.re +15 -0
  135. data/test/sample-book/src/sty/jumoline.sty +310 -0
  136. data/test/sample-book/src/sty/reviewmacro.sty +39 -0
  137. data/test/sample-book/src/style.css +251 -0
  138. data/test/sample-book/src/vendor/jumoline/README +29 -0
  139. data/test/sample-book/src/vendor/jumoline/jumoline.dtx +2988 -0
  140. data/test/sample-book/src/vendor/jumoline/jumoline.ins +6 -0
  141. data/test/test.re +43 -0
  142. data/test/test_book.rb +556 -0
  143. data/test/test_book_chapter.rb +280 -0
  144. data/test/test_book_part.rb +54 -0
  145. data/test/test_builder.rb +80 -0
  146. data/test/test_catalog.rb +119 -0
  147. data/test/test_catalog_converter_cmd.rb +73 -0
  148. data/test/test_compiler.rb +92 -0
  149. data/test/test_configure.rb +50 -0
  150. data/test/test_epub3maker.rb +529 -0
  151. data/test/test_epubmaker.rb +569 -0
  152. data/test/test_epubmaker_cmd.rb +40 -0
  153. data/test/test_helper.rb +92 -0
  154. data/test/test_htmlbuilder.rb +1114 -0
  155. data/test/test_htmltoc.rb +32 -0
  156. data/test/test_htmlutils.rb +50 -0
  157. data/test/test_i18n.rb +180 -0
  158. data/test/test_idgxmlbuilder.rb +608 -0
  159. data/test/test_image_finder.rb +82 -0
  160. data/test/test_inaobuilder.rb +245 -0
  161. data/test/test_index.rb +174 -0
  162. data/test/test_latexbuilder.rb +732 -0
  163. data/test/test_lineinput.rb +182 -0
  164. data/test/test_makerhelper.rb +66 -0
  165. data/test/test_markdownbuilder.rb +125 -0
  166. data/test/test_pdfmaker.rb +171 -0
  167. data/test/test_pdfmaker_cmd.rb +40 -0
  168. data/test/test_preprocessor.rb +23 -0
  169. data/test/test_review_ext.rb +31 -0
  170. data/test/test_template.rb +26 -0
  171. data/test/test_textutils.rb +32 -0
  172. data/test/test_topbuilder.rb +291 -0
  173. data/test/test_uuid.rb +157 -0
  174. metadata +357 -0
data/lib/lineinput.rb ADDED
@@ -0,0 +1,107 @@
1
+ #
2
+ # $Id: lineinput.rb 2226 2006-04-15 03:05:09Z aamine $
3
+ #
4
+ # Copyright (c) 2002-2005 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU LGPL, Lesser General Public License version 2.1.
9
+ #
10
+
11
+ class LineInput
12
+
13
+ def initialize(f)
14
+ @input = f
15
+ @buf = []
16
+ @lineno = 0
17
+ @eof_p = false
18
+ end
19
+
20
+ def inspect
21
+ "\#<#{self.class} file=#{@input.inspect} line=#{lineno()}>"
22
+ end
23
+
24
+ def eof?
25
+ @eof_p
26
+ end
27
+
28
+ def lineno
29
+ @lineno
30
+ end
31
+
32
+ def gets
33
+ unless @buf.empty?
34
+ @lineno += 1
35
+ return @buf.pop
36
+ end
37
+ return nil if @eof_p # to avoid ARGF blocking.
38
+ line = @input.gets
39
+ @eof_p = true unless line
40
+ @lineno += 1
41
+ line
42
+ end
43
+
44
+ def ungets(line)
45
+ return unless line
46
+ @lineno -= 1
47
+ @buf.push line
48
+ line
49
+ end
50
+
51
+ def each
52
+ while line = gets()
53
+ yield line
54
+ end
55
+ end
56
+
57
+ def while_match(re)
58
+ while line = gets()
59
+ unless re =~ line
60
+ ungets line
61
+ return
62
+ end
63
+ yield line
64
+ end
65
+ nil
66
+ end
67
+
68
+ def getlines_while(re)
69
+ buf = []
70
+ while_match(re) do |line|
71
+ buf.push line
72
+ end
73
+ buf
74
+ end
75
+
76
+ alias_method :span, :getlines_while # from Haskell
77
+
78
+ def until_match(re)
79
+ while line = gets()
80
+ if re =~ line
81
+ ungets line
82
+ return
83
+ end
84
+ yield line
85
+ end
86
+ nil
87
+ end
88
+
89
+ def getlines_until(re)
90
+ buf = []
91
+ until_match(re) do |line|
92
+ buf.push line
93
+ end
94
+ buf
95
+ end
96
+
97
+ alias_method :break, :getlines_until # from Haskell
98
+
99
+ def until_terminator(re)
100
+ while line = gets()
101
+ return if re =~ line # discard terminal line
102
+ yield line
103
+ end
104
+ nil
105
+ end
106
+
107
+ end
data/lib/review.rb ADDED
@@ -0,0 +1,3 @@
1
+ Dir["#{File.dirname(__FILE__)}/review/*.rb"].sort.each do |path|
2
+ require "review/#{File.basename(path, '.rb')}"
3
+ end
@@ -0,0 +1,43 @@
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
+
13
+ require 'review/exception'
14
+ require 'review/extentions'
15
+
16
+ require 'review/book/base'
17
+ require 'review/book/chapter'
18
+ require 'review/book/part'
19
+ require 'review/book/page_metric'
20
+ require 'review/book/volume'
21
+ require 'review/book/index'
22
+
23
+ module ReVIEW
24
+ @default_book = nil
25
+
26
+ def ReVIEW.book
27
+ @default_book ||= Book::Base.load
28
+ end
29
+
30
+ module Book
31
+ def self.load_default
32
+ Base.load_default
33
+ end
34
+
35
+ def self.load(dir)
36
+ Base.load dir
37
+ end
38
+
39
+ def self.update_rubyenv(dir)
40
+ Base.update_rubyenv dir
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,401 @@
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
+ require 'review/configure'
13
+ require 'review/catalog'
14
+
15
+ module ReVIEW
16
+ module Book
17
+ class Base
18
+
19
+ attr_writer :config
20
+
21
+ def self.load_default
22
+ warn 'Book::Base.load_default() is obsoleted. Use Book::Base.load().'
23
+ load()
24
+ end
25
+
26
+ def self.load(dir = ".")
27
+ update_rubyenv dir
28
+ new(dir)
29
+ end
30
+
31
+ @basedir_seen = {}
32
+
33
+ def self.update_rubyenv(dir)
34
+ return if @basedir_seen.key?(dir)
35
+ if File.file?("#{dir}/review-ext.rb")
36
+ if ENV["REVIEW_SAFE_MODE"].to_i & 2 > 0
37
+ warn "review-ext.rb is prohibited in safe mode. ignored."
38
+ else
39
+ Kernel.load File.expand_path("#{dir}/review-ext.rb")
40
+ end
41
+ end
42
+ @basedir_seen[dir] = true
43
+ end
44
+
45
+ def initialize(basedir)
46
+ @basedir = basedir
47
+ @parts = nil
48
+ @chapter_index = nil
49
+ @config = ReVIEW::Configure.values
50
+ @catalog = nil
51
+ end
52
+
53
+ def bib_file
54
+ config["bib_file"]
55
+ end
56
+
57
+ def reject_file
58
+ config["reject_file"]
59
+ end
60
+
61
+ def ext
62
+ config["ext"]
63
+ end
64
+
65
+ def image_dir
66
+ config["image_dir"]
67
+ end
68
+
69
+ def image_types
70
+ config["image_types"]
71
+ end
72
+
73
+ def image_types=(types)
74
+ config["image_types"] = types
75
+ end
76
+
77
+ def page_metric
78
+ if config["page_metric"].respond_to?(:downcase) && config["page_metric"].upcase =~ /^[A-Z0-9_]+$/
79
+ ReVIEW::Book::PageMetric.const_get(config["page_metric"].upcase)
80
+ elsif config["page_metric"].kind_of?(Array) && config["page_metric"].size == 5
81
+ ReVIEW::Book::PageMetric.new(*config["page_metric"])
82
+ else
83
+ config["page_metric"]
84
+ end
85
+ end
86
+
87
+ def htmlversion
88
+ if config["htmlversion"].blank?
89
+ nil
90
+ else
91
+ config["htmlversion"].to_i
92
+ end
93
+ end
94
+
95
+ def parts
96
+ @parts ||= read_parts()
97
+ end
98
+
99
+ def parts_in_file
100
+ parts.find_all{|part|
101
+ part if part.present? and part.file?
102
+ }
103
+ end
104
+
105
+ def part(n)
106
+ parts.detect {|part| part.number == n }
107
+ end
108
+
109
+ def each_part(&block)
110
+ parts.each(&block)
111
+ end
112
+
113
+ def chapters
114
+ parts().map {|p| p.chapters }.flatten
115
+ end
116
+
117
+ def each_chapter(&block)
118
+ chapters.each(&block)
119
+ end
120
+
121
+ def each_chapter_r(&block)
122
+ chapters.reverse_each(&block)
123
+ end
124
+
125
+ def chapter_index
126
+ return @chapter_index if @chapter_index
127
+
128
+ contents = chapters()
129
+ parts().each do |prt|
130
+ if prt.id.present?
131
+ contents << prt
132
+ end
133
+ end
134
+ @chapter_index = ChapterIndex.new(contents)
135
+ end
136
+
137
+ def chapter(id)
138
+ chapter_index()[id]
139
+ end
140
+
141
+ def next_chapter(chapter)
142
+ finded = false
143
+ each_chapter do |c|
144
+ return c if finded
145
+ finded = true if c == chapter
146
+ end
147
+ nil # not found
148
+ end
149
+
150
+ def prev_chapter(chapter)
151
+ finded = false
152
+ each_chapter_r do |c|
153
+ return c if finded
154
+ finded = true if c == chapter
155
+ end
156
+ nil # not found
157
+ end
158
+
159
+ def volume
160
+ vol = Volume.sum(chapters.map {|chap| chap.volume })
161
+ vol.page_per_kbyte = page_metric.page_per_kbyte
162
+ vol
163
+ end
164
+
165
+ def config
166
+ @config ||= Configure.values
167
+ end
168
+
169
+ # backward compatible
170
+ def param=(param)
171
+ @config = param
172
+ end
173
+
174
+ def load_config(filename)
175
+ new_conf = YAML.load_file(filename)
176
+ @config.merge!(new_conf)
177
+ end
178
+
179
+ # backward compatible
180
+ def param
181
+ @config
182
+ end
183
+
184
+ def catalog
185
+ return @catalog if @catalog.present?
186
+
187
+ catalogfile_path = "#{basedir}/#{config["catalogfile"]}"
188
+ if File.file? catalogfile_path
189
+ @catalog = Catalog.new(File.open catalogfile_path)
190
+ end
191
+
192
+ @catalog
193
+ end
194
+
195
+ def read_CHAPS
196
+ if catalog
197
+ catalog.chaps
198
+ else
199
+ read_FILE(config["chapter_file"])
200
+ end
201
+ end
202
+
203
+ def read_PREDEF
204
+ if catalog
205
+ catalog.predef
206
+ else
207
+ read_FILE(config["predef_file"])
208
+ end
209
+ end
210
+
211
+ def read_APPENDIX
212
+ if catalog
213
+ catalog.appendix
214
+ else
215
+ read_FILE(config["postdef_file"]) # for backward compatibility
216
+ end
217
+ end
218
+
219
+ def read_POSTDEF
220
+ if catalog
221
+ catalog.postdef
222
+ else
223
+ ""
224
+ end
225
+ end
226
+
227
+ def read_PART
228
+ return @read_part if @read_part
229
+
230
+ if catalog
231
+ @read_part = catalog.parts
232
+ else
233
+ @read_part = File.read("#{@basedir}/#{config["part_file"]}")
234
+ end
235
+ end
236
+
237
+ def part_exist?
238
+ if catalog
239
+ catalog.parts.present?
240
+ else
241
+ File.exist?("#{@basedir}/#{config["part_file"]}")
242
+ end
243
+ end
244
+
245
+ def read_bib
246
+ File.read("#{@basedir}/#{bib_file}")
247
+ end
248
+
249
+ def bib_exist?
250
+ File.exist?("#{@basedir}/#{bib_file}")
251
+ end
252
+
253
+ def prefaces
254
+ if catalog
255
+ return mkpart_from_namelist(catalog.predef.split("\n"))
256
+ end
257
+
258
+ if File.file?("#{@basedir}/#{config["predef_file"]}")
259
+ begin
260
+ return mkpart_from_namelistfile("#{@basedir}/#{config["predef_file"]}")
261
+ rescue FileNotFound => err
262
+ raise FileNotFound, "preface #{err.message}"
263
+ end
264
+ end
265
+ end
266
+
267
+ def appendix
268
+ if catalog
269
+ names = catalog.appendix.split("\n")
270
+ chaps = names.each_with_index.map {|n, idx|
271
+ mkchap_ifexist(n, idx)
272
+ }.compact
273
+ return mkpart(chaps)
274
+ end
275
+
276
+ if File.file?("#{@basedir}/#{config["postdef_file"]}")
277
+ begin
278
+ return mkpart_from_namelistfile("#{@basedir}/#{config["postdef_file"]}")
279
+ rescue FileNotFound => err
280
+ raise FileNotFound, "postscript #{err.message}"
281
+ end
282
+ end
283
+ end
284
+
285
+ def postscripts
286
+ if catalog
287
+ mkpart_from_namelist(catalog.postdef.split("\n"))
288
+ end
289
+ end
290
+
291
+ def basedir
292
+ @basedir
293
+ end
294
+
295
+ private
296
+
297
+ def read_parts
298
+ list = parse_chapters
299
+ if pre = prefaces
300
+ list.unshift pre
301
+ end
302
+ if app = appendix
303
+ list.push app
304
+ end
305
+ if post = postscripts
306
+ list.push post
307
+ end
308
+ list
309
+ end
310
+
311
+ def parse_chapters
312
+ part = 0
313
+ num = 0
314
+
315
+ if catalog
316
+ return catalog.parts_with_chaps.map do |entry|
317
+ if entry.is_a? Hash
318
+ chaps = entry.values.first.map do |chap|
319
+ Chapter.new(self, (num += 1), chap, "#{@basedir}/#{chap}")
320
+ end
321
+ Part.new(self, (part += 1), chaps, read_PART.split("\n")[part - 1])
322
+ else
323
+ chap = Chapter.new(self, (num += 1), entry, "#{@basedir}/#{entry}")
324
+ Part.new(self, nil, [chap])
325
+ end
326
+ end
327
+ end
328
+
329
+ chap = read_CHAPS()\
330
+ .strip.lines.map {|line| line.strip }.join("\n").split(/\n{2,}/)\
331
+ .map {|part_chunk|
332
+ chaps = part_chunk.split.map {|chapid|
333
+ Chapter.new(self, (num += 1), chapid, "#{@basedir}/#{chapid}")
334
+ }
335
+ if part_exist? && read_PART.split("\n").size >= part
336
+ Part.new(self, (part += 1), chaps, read_PART.split("\n")[part-1])
337
+ else
338
+ Part.new(self, (part += 1), chaps)
339
+ end
340
+ }
341
+ return chap
342
+ end
343
+
344
+ def mkpart_from_namelistfile(path)
345
+ chaps = []
346
+ File.read(path).split.each_with_index do |name, idx|
347
+ name.sub!(/\A\xEF\xBB\xBF/u, '') # remove BOM
348
+ if path =~ /PREDEF/
349
+ chaps << mkchap(name)
350
+ else
351
+ chaps << mkchap(name, idx + 1)
352
+ end
353
+ end
354
+ mkpart(chaps)
355
+ end
356
+
357
+ def mkpart_from_namelist(names)
358
+ mkpart(names.map {|n| mkchap_ifexist(n) }.compact)
359
+ end
360
+
361
+ def mkpart(chaps)
362
+ chaps.empty? ? nil : Part.new(self, nil, chaps)
363
+ end
364
+
365
+ def mkchap(name, number = nil)
366
+ name += ext if File.extname(name) == ""
367
+ path = "#{@basedir}/#{name}"
368
+ raise FileNotFound, "file not exist: #{path}" unless File.file?(path)
369
+ Chapter.new(self, number, name, path)
370
+ end
371
+
372
+ def mkchap_ifexist(name, idx = nil)
373
+ name += ext if File.extname(name) == ""
374
+ path = "#{@basedir}/#{name}"
375
+ if File.file?(path)
376
+ idx += 1 if idx
377
+ Chapter.new(self, idx, name, path)
378
+ end
379
+ end
380
+
381
+ def read_FILE(filename)
382
+ res = ""
383
+ File.open("#{@basedir}/#{filename}") do |f|
384
+ while line = f.gets
385
+ line.sub!(/\A\xEF\xBB\xBF/u, '') # remove BOM
386
+ if /\A#/ =~ line
387
+ next
388
+ end
389
+ line.gsub!(/#.*$/, "")
390
+ res << line
391
+ end
392
+ end
393
+ res
394
+ rescue Errno::ENOENT
395
+ Dir.glob("#{@basedir}/*#{ext()}").sort.join("\n")
396
+ rescue Errno::EISDIR
397
+ ""
398
+ end
399
+ end
400
+ end
401
+ end