review 0.6.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 (50) hide show
  1. data/COPYING +515 -0
  2. data/ChangeLog +1278 -0
  3. data/README.rdoc +21 -0
  4. data/Rakefile +42 -0
  5. data/VERSION +1 -0
  6. data/bin/review-check +190 -0
  7. data/bin/review-checkdep +63 -0
  8. data/bin/review-compile +165 -0
  9. data/bin/review-epubmaker +525 -0
  10. data/bin/review-index +108 -0
  11. data/bin/review-preproc +140 -0
  12. data/bin/review-validate +51 -0
  13. data/bin/review-vol +106 -0
  14. data/doc/format.re +486 -0
  15. data/doc/format.txt +434 -0
  16. data/doc/format_idg.txt +194 -0
  17. data/doc/format_sjis.txt +313 -0
  18. data/doc/sample.css +91 -0
  19. data/doc/sample.yaml +46 -0
  20. data/lib/lineinput.rb +155 -0
  21. data/lib/review/book.rb +580 -0
  22. data/lib/review/builder.rb +274 -0
  23. data/lib/review/compat.rb +22 -0
  24. data/lib/review/compiler.rb +483 -0
  25. data/lib/review/epubbuilder.rb +692 -0
  26. data/lib/review/ewbbuilder.rb +382 -0
  27. data/lib/review/exception.rb +21 -0
  28. data/lib/review/htmlbuilder.rb +370 -0
  29. data/lib/review/htmllayout.rb +19 -0
  30. data/lib/review/htmlutils.rb +27 -0
  31. data/lib/review/idgxmlbuilder.rb +1078 -0
  32. data/lib/review/index.rb +224 -0
  33. data/lib/review/latexbuilder.rb +420 -0
  34. data/lib/review/latexindex.rb +35 -0
  35. data/lib/review/latexutils.rb +52 -0
  36. data/lib/review/preprocessor.rb +520 -0
  37. data/lib/review/textutils.rb +19 -0
  38. data/lib/review/tocparser.rb +333 -0
  39. data/lib/review/tocprinter.rb +220 -0
  40. data/lib/review/topbuilder.rb +572 -0
  41. data/lib/review/unfold.rb +138 -0
  42. data/lib/review/volume.rb +66 -0
  43. data/lib/review.rb +4 -0
  44. data/review.gemspec +93 -0
  45. data/setup.rb +1587 -0
  46. data/test/test_epubbuilder.rb +73 -0
  47. data/test/test_helper.rb +2 -0
  48. data/test/test_htmlbuilder.rb +42 -0
  49. data/test/test_latexbuilder.rb +74 -0
  50. metadata +122 -0
@@ -0,0 +1,19 @@
1
+ # $Id: textutils.rb 2192 2005-11-13 11:55:42Z aamine $
2
+
3
+ module ReVIEW
4
+
5
+ module TextUtils
6
+
7
+ def detab(str, ts = 8)
8
+ add = 0
9
+ len = nil
10
+ str.gsub(/\t/) {
11
+ len = ts - ($`.size + add) % ts
12
+ add += len - 1
13
+ ' ' * len
14
+ }
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,333 @@
1
+ #
2
+ # $Id: tocparser.rb 4268 2009-05-27 04:17:08Z kmuto $
3
+ #
4
+ # Copyright (c) 2002-2007 Minero Aoki
5
+ # 2008-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/preprocessor'
14
+ require 'review/book'
15
+ require 'review/volume'
16
+ require 'forwardable'
17
+
18
+ module ReVIEW
19
+
20
+ class TOCParser
21
+
22
+ def TOCParser.parse(chap)
23
+ chap.open {|f|
24
+ stream = Preprocessor::Strip.new(f)
25
+ new.parse(stream, chap.id, chap.path).map {|root|
26
+ root.number = chap.number
27
+ root
28
+ }
29
+ }
30
+ end
31
+
32
+ def parse(f, id, filename)
33
+ roots = []
34
+ path = []
35
+
36
+ while line = f.gets
37
+ case line
38
+ when /\A\s*\z/
39
+ ;
40
+ when /\A(={2,})[\[\s]/
41
+ lev = $1.size
42
+ error! filename, f.lineno, "section level too deep: #{lev}" if lev > 5
43
+ if path.empty?
44
+ # missing chapter label
45
+ path.push Chapter.new(get_label(line), id, filename)
46
+ roots.push path.first
47
+ end
48
+ new = Section.new(lev, get_label(line))
49
+ until path.last.level < new.level
50
+ path.pop
51
+ end
52
+ path.last.add_child new
53
+ path.push new
54
+
55
+ when /\A= /
56
+ path.clear
57
+ path.push Chapter.new(get_label(line), id, filename)
58
+ roots.push path.first
59
+
60
+ when %r<\A//\w+(?:\[.*?\])*\{\s*\z>
61
+ if path.empty?
62
+ error! filename, f.lineno, 'list found before section label'
63
+ end
64
+ path.last.add_child(list = List.new)
65
+ beg = f.lineno
66
+ list.add line
67
+ while line = f.gets
68
+ break if %r<\A//\}> =~ line
69
+ list.add line
70
+ end
71
+ error! filename, beg, 'unterminated list' unless line
72
+
73
+ when %r<\A//\w>
74
+ ;
75
+ else
76
+ #if path.empty?
77
+ # error! filename, f.lineno, 'text found before section label'
78
+ #end
79
+ next if path.empty?
80
+ path.last.add_child(par = Paragraph.new)
81
+ par.add line
82
+ while line = f.gets
83
+ break if /\A\s*\z/ =~ line
84
+ par.add line
85
+ end
86
+ end
87
+ end
88
+
89
+ roots
90
+ end
91
+
92
+ def get_label(line)
93
+ line.strip.sub(/\A=+\s*/, '')
94
+ end
95
+
96
+ def error!(filename, lineno, msg)
97
+ raise "#{filename}:#{lineno}: #{msg}"
98
+ end
99
+
100
+
101
+ class Node
102
+
103
+ def initialize(children = [])
104
+ @children = children
105
+ end
106
+
107
+ attr_reader :children
108
+
109
+ def add_child(c)
110
+ @children.push c
111
+ end
112
+
113
+ def each_node(&block)
114
+ @children.each do |c|
115
+ yield c
116
+ c.each(&block)
117
+ end
118
+ end
119
+
120
+ def each_child(&block)
121
+ @children.each(&block)
122
+ end
123
+
124
+ def chapter?
125
+ false
126
+ end
127
+
128
+ def each_section(&block)
129
+ @children.each do |n|
130
+ n.yield_section(&block)
131
+ end
132
+ end
133
+
134
+ def each_section_with_index
135
+ i = 0
136
+ each_section do |n|
137
+ yield n, i
138
+ i += 1
139
+ end
140
+ end
141
+
142
+ def n_sections
143
+ cnt = 0
144
+ @children.each do |n|
145
+ n.yield_section { cnt += 1 }
146
+ end
147
+ cnt
148
+ end
149
+
150
+ end
151
+
152
+
153
+ class Section < Node
154
+
155
+ def initialize(level, label, path = nil)
156
+ super()
157
+ @level = level
158
+ @label = label
159
+ @filename = (path ? real_filename(path) : nil)
160
+ end
161
+
162
+ def real_filename(path)
163
+ if FileTest.symlink?(path)
164
+ File.basename(File.readlink(path))
165
+ else
166
+ File.basename(path)
167
+ end
168
+ end
169
+ private :real_filename
170
+
171
+ attr_reader :level
172
+ attr_reader :label
173
+
174
+ def display_label
175
+ if @filename
176
+ @label + ' ' + @filename
177
+ else
178
+ @label
179
+ end
180
+ end
181
+
182
+ def estimated_lines
183
+ @children.inject(0) {|sum, n| sum + n.estimated_lines }
184
+ end
185
+
186
+ def yield_section
187
+ yield self
188
+ end
189
+
190
+ def inspect
191
+ "\#<#{self.class} level=#{@level} #{@label}>"
192
+ end
193
+
194
+ end
195
+
196
+
197
+ class Chapter < Section
198
+
199
+ def initialize(label, id, path)
200
+ super 1, label, path
201
+ @chapter_id = id
202
+ @path = path
203
+ @volume = nil
204
+ @number = nil
205
+ end
206
+
207
+ attr_accessor :number
208
+
209
+ def chapter?
210
+ true
211
+ end
212
+
213
+ attr_reader :chapter_id
214
+
215
+ def volume
216
+ return @volume if @volume
217
+ return Volume.dummy unless @path
218
+ @volume = Volume.count_file(@path)
219
+ @volume.lines = estimated_lines()
220
+ @volume
221
+ end
222
+
223
+ def inspect
224
+ "\#<#{self.class} #{@filename}>"
225
+ end
226
+
227
+ end
228
+
229
+
230
+ class Paragraph < Node
231
+
232
+ def initialize
233
+ @bytes = 0
234
+ end
235
+
236
+ def inspect
237
+ "\#<#{self.class}>"
238
+ end
239
+
240
+ def add(line)
241
+ @bytes += line.strip.bytesize
242
+ end
243
+
244
+ def estimated_lines
245
+ (@bytes + 2) / ReVIEW.book.page_metric.text.n_columns + 1
246
+ end
247
+
248
+ def yield_section
249
+ end
250
+
251
+ end
252
+
253
+
254
+ class List < Node
255
+
256
+ def initialize
257
+ @lines = 0
258
+ end
259
+
260
+ def inspect
261
+ "\#<#{self.class}>"
262
+ end
263
+
264
+ def add(line)
265
+ @lines += 1
266
+ end
267
+
268
+ def estimated_lines
269
+ @lines + 2
270
+ end
271
+
272
+ def yield_section
273
+ end
274
+
275
+ end
276
+
277
+ end
278
+
279
+
280
+ module TOCRoot
281
+ def level
282
+ 0
283
+ end
284
+
285
+ def chapter?
286
+ false
287
+ end
288
+
289
+ def each_section_with_index
290
+ idx = -1
291
+ each_section do |node|
292
+ yield node, (idx += 1)
293
+ end
294
+ end
295
+
296
+ def each_section(&block)
297
+ each_chapter do |chap|
298
+ yield chap.toc
299
+ end
300
+ end
301
+
302
+ def n_sections
303
+ chapters.size
304
+ end
305
+
306
+ def estimated_lines
307
+ chapters.inject(0) {|sum, chap| sum + chap.toc.estimated_lines }
308
+ end
309
+ end
310
+
311
+ class Book # reopen
312
+ include TOCRoot
313
+ end
314
+
315
+ class ChapterSet # reopen
316
+ include TOCRoot
317
+ end
318
+
319
+ class Part
320
+ include TOCRoot
321
+ end
322
+
323
+ class Chapter # reopen
324
+ def toc
325
+ @toc ||= TOCParser.parse(self)
326
+ unless @toc.size == 1
327
+ $stderr.puts "warning: chapter #{title} contains more than 1 chapter"
328
+ end
329
+ @toc.first
330
+ end
331
+ end
332
+
333
+ end
@@ -0,0 +1,220 @@
1
+ #
2
+ # $Id: tocprinter.rb 4309 2009-07-19 04:15:02Z aamine $
3
+ #
4
+ # Copyright (c) 2002-2007 Minero Aoki
5
+ # 2008-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 LGPL, see the file "COPYING".
11
+ #
12
+
13
+ require 'review/htmlutils'
14
+ require 'review/htmllayout'
15
+ require 'nkf'
16
+
17
+ module ReVIEW
18
+
19
+ class TOCPrinter
20
+
21
+ def TOCPrinter.default_upper_level
22
+ 99 # no one use 99 level nest
23
+ end
24
+
25
+ def initialize(print_upper, param)
26
+ @print_upper = print_upper
27
+ @param = param
28
+ end
29
+
30
+ def print?(level)
31
+ level <= @print_upper
32
+ end
33
+
34
+ def nkffilter(line)
35
+ inc = ""
36
+ outc = "-w"
37
+ if @param["inencoding"] =~ /^EUC$/
38
+ inc = "-E"
39
+ elsif @param["inencoding"] =~ /^SJIS$/
40
+ inc = "-S"
41
+ elsif @param["inencoding"] =~ /^JIS$/
42
+ inc = "-J"
43
+ end
44
+
45
+ if @param["outencoding"] =~ /^EUC$/
46
+ outc = "-e"
47
+ elsif @param["outencoding"] =~ /^SJIS$/
48
+ outc = "-s"
49
+ elsif @param["outencoding"] =~ /^JIS$/
50
+ outc = "-j"
51
+ end
52
+
53
+ NKF.nkf("#{inc} #{outc}", line)
54
+ end
55
+ end
56
+
57
+
58
+ class TextTOCPrinter < TOCPrinter
59
+ def print_book(book)
60
+ print_children book
61
+ end
62
+
63
+ private
64
+
65
+ def print_children(node)
66
+ return unless print?(node.level + 1)
67
+ node.each_section_with_index do |section, idx|
68
+ print_node idx+1, section
69
+ print_children section
70
+ end
71
+ end
72
+
73
+ def print_node(number, node)
74
+ if node.chapter?
75
+ vol = node.volume
76
+ printf "%3s %3dKB %6dC %5dL %s (%s)\n",
77
+ chapnumstr(node.number),
78
+ vol.kbytes, vol.chars, vol.lines,
79
+ nkffilter(node.label), node.chapter_id
80
+ else
81
+ printf "%17s %5dL %s\n",
82
+ '', node.estimated_lines,
83
+ nkffilter(" #{' ' * (node.level - 1)}#{number} #{node.label}")
84
+ end
85
+ end
86
+
87
+ def chapnumstr(n)
88
+ n ? sprintf('%2d.', n) : ' '
89
+ end
90
+
91
+ def volume_columns(level, volstr)
92
+ cols = ["", "", "", nil]
93
+ cols[level - 1] = volstr
94
+ cols[0, 3] # does not display volume of level-4 section
95
+ end
96
+
97
+ end
98
+
99
+
100
+ class HTMLTOCPrinter < TOCPrinter
101
+
102
+ include HTMLUtils
103
+
104
+ def print_book(book)
105
+ return unless print?(1)
106
+ html = ""
107
+ book.each_part do |part|
108
+ html << h1(part.name) if part.name
109
+ part.each_section do |chap|
110
+ if chap.number
111
+ name = "chap#{chap.number}"
112
+ label = "第#{chap.number}章 #{chap.label}"
113
+ html << h2(a_name(escape_html(name), escape_html(label)))
114
+ else
115
+ label = "#{chap.label}"
116
+ html << h2(escape_html(label))
117
+ end
118
+ return unless print?(2)
119
+ if print?(3)
120
+ html << chap_sections_to_s(chap)
121
+ else
122
+ html << chapter_to_s(chap)
123
+ end
124
+ end
125
+ end
126
+ puts HTMLLayout.new(html, "目次", File.join(book.basedir, "layouts", "layout.erb")).result
127
+ end
128
+
129
+ private
130
+
131
+ def chap_sections_to_s(chap)
132
+ res = []
133
+ res << "<ol>"
134
+ chap.each_section do |sec|
135
+ res << li(escape_html(sec.label))
136
+ end
137
+ res << "</ol>"
138
+ return res.join("\n")
139
+ end
140
+
141
+ def print_chapter_to_s(chap)
142
+ res = []
143
+ chap.each_section do |sec|
144
+ res << h3(escape_html(sec.label))
145
+ next unless print?(4)
146
+ next if sec.n_sections == 0
147
+ res << "<ul>"
148
+ sec.each_section do |node|
149
+ res << li(escape_html(node.label))
150
+ end
151
+ res << "</ul>"
152
+ end
153
+ return res.join("\n")
154
+ end
155
+
156
+ def h1(label)
157
+ "<h1>#{label}</h1>"
158
+ end
159
+
160
+ def h2(label)
161
+ "<h2>#{label}</h2>"
162
+ end
163
+
164
+ def h3(label)
165
+ "<h3>#{label}</h3>"
166
+ end
167
+
168
+ def li(content)
169
+ "<li>#{content}</li>"
170
+ end
171
+
172
+ def a_name(name, label)
173
+ %Q(<a name="#{name}">#{label}</a>)
174
+ end
175
+
176
+ end
177
+
178
+ class IDGTOCPrinter < TOCPrinter
179
+ def print_book(book)
180
+ puts %Q(<?xml version="1.0" encoding="UTF-8"?>)
181
+ puts nkffilter(%Q(<doc xmlns:aid='http://ns.adobe.com/AdobeInDesign/4.0/'><title aid:pstyle="h0">1 パート1</title><?dtp level="0" section="第1部 パート1"?>)) # FIXME: 部タイトルを取るには? & 部ごとに結果を分けるには?
182
+ puts %Q(<ul aid:pstyle='ul-partblock'>)
183
+ print_children book
184
+ puts %Q(</ul></doc>)
185
+ end
186
+
187
+ private
188
+
189
+ def print_children(node)
190
+ return unless print?(node.level + 1)
191
+ node.each_section_with_index do |sec, idx|
192
+ print_node idx+1, sec
193
+ print_children sec
194
+ end
195
+ end
196
+
197
+ LABEL_LEN = 54
198
+
199
+ def print_node(seq, node)
200
+ if node.chapter?
201
+ vol = node.volume
202
+ printf "<li aid:pstyle='ul-part'>%s</li>\n",
203
+ nkffilter("#{chapnumstr(node.number)}#{node.label}")
204
+ else
205
+ printf "<li>%-#{LABEL_LEN}s\n",
206
+ nkffilter(" #{' ' * (node.level - 1)}#{seq} #{node.label}</li>")
207
+ end
208
+ end
209
+
210
+ def chapnumstr(n)
211
+ n ? nkffilter(sprintf('第%d章 ', n)) : ''
212
+ end
213
+
214
+ def volume_columns(level, volstr)
215
+ cols = ["", "", "", nil]
216
+ cols[level - 1] = volstr
217
+ cols[0, 3]
218
+ end
219
+ end
220
+ end