review 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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