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
data/README.rdoc ADDED
@@ -0,0 +1,21 @@
1
+ = ReVIEW
2
+
3
+ ReVIEW is a easy-to-use digital publishing system for books and ebooks.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == License
16
+
17
+ LGPL. See COPYING file.
18
+
19
+ == Copyright
20
+
21
+ Copyright (c) 2006-2010 Minero Aoki, Kenshi Muto, Masayoshi Takahashi.
data/Rakefile ADDED
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/clean'
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gem|
9
+ gem.name = "review"
10
+ gem.summary = %Q{ReVIEW: a easy-to-use digital publishing system}
11
+ gem.description = %Q{ReVIEW is a digital publishing system for books and ebooks. It supports InDesin, EPUB and LaTeX.}
12
+ gem.email = "kmuto@debian.org"
13
+ gem.homepage = "http://github.com/kmuto/review"
14
+ gem.authors = ["kmuto", "takahashim"]
15
+ # gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
21
+ end
22
+
23
+
24
+ task :test => :check_dependencies
25
+
26
+ task :default => [:test]
27
+
28
+ Rake::TestTask.new("test") do |t|
29
+ t.libs << "test"
30
+ t.pattern = "test/test_*.rb"
31
+ t.verbose = true
32
+ end
33
+
34
+ require 'rake/rdoctask'
35
+ Rake::RDocTask.new do |rdoc|
36
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
37
+
38
+ rdoc.rdoc_dir = 'rdoc'
39
+ rdoc.title = "review #{version}"
40
+ rdoc.rdoc_files.include('README*')
41
+ rdoc.rdoc_files.include('lib/**/*.rb')
42
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.6.0
data/bin/review-check ADDED
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ #
4
+ # Copyright (c) 1999-2007 Minero Aoki
5
+ # Copyright (c) 2010 Kenshi Muto, Minero Aoki
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 'pathname'
14
+
15
+ bindir = Pathname.new(__FILE__).realpath.dirname
16
+ $LOAD_PATH.unshift((bindir + '../lib').realpath)
17
+
18
+ require 'review/book'
19
+ require 'optparse'
20
+ require 'nkf'
21
+
22
+ def sigmain
23
+ Signal.trap(:INT) { exit 1 }
24
+ Signal.trap(:PIPE, 'IGNORE')
25
+ main
26
+ rescue Errno::EPIPE
27
+ exit 0
28
+ end
29
+
30
+ def main
31
+ $KCODE = 'UTF-8' unless defined?(Encoding)
32
+ @param = {
33
+ "inencoding" => "UTF-8",
34
+ "outencoding" => "UTF-8"
35
+ }
36
+
37
+ modes = nil
38
+ files = ARGV unless ARGV.empty?
39
+ parser = OptionParser.new
40
+ parser.on('--inencoding=ENCODING', 'Set input encoding. (UTF-8, EUC, JIS, and SJIS)') {|enc|
41
+ @param["inencoding"] = enc
42
+ }
43
+ parser.on('--outencoding=ENCODING', 'Set output encoding. (UTF-8[default], EUC, JIS, and SJIS)') {|enc|
44
+ @param["outencoding"] = enc
45
+ }
46
+ parser.on('-a', '--all-chapters', 'Check all chapters.') {
47
+ files = ReVIEW.book.chapters.map {|ent| ent.path }
48
+ }
49
+ parser.on('-s', '--section N', 'Check section N.') {|n|
50
+ ents = ReVIEW.env.parts[Integer(n) - 1] or
51
+ raise ReVIEW::ApplicationError, "section #{n} not exist"
52
+ files = ents.map {|ent| ent.path }
53
+ }
54
+ parser.on('--text', 'Check text.') {
55
+ (modes ||= []).push :text
56
+ }
57
+ parser.on('--help', 'print this message and quit.') {
58
+ puts parser.help
59
+ exit 0
60
+ }
61
+ begin
62
+ parser.parse!
63
+ rescue OptionParser::ParseError => err
64
+ $stderr.puts err.message
65
+ $stderr.puts parser.help
66
+ exit 1
67
+ end
68
+ unless files
69
+ $stderr.puts "no input"
70
+ exit 1
71
+ end
72
+ modes ||= [:text]
73
+
74
+ modes.each do |mode|
75
+ case mode
76
+ when :text
77
+ check_text files
78
+ else
79
+ raise 'must not happen'
80
+ end
81
+ end
82
+ end
83
+
84
+ def check_text(files)
85
+ re, neg = words_re(ReVIEW.book.basedir + ReVIEW.book.reject_file)
86
+ files.each do |path|
87
+ File.open(path) {|f|
88
+ each_paragraph(f) do |para, lineno|
89
+ s = para.join('')
90
+ if m = re.match(s)
91
+ next if m[0] == $ReVIEW_utils_word_ok
92
+ next if neg and neg =~ s
93
+ str, offset = find_line(para, re)
94
+ out = sprintf("%s:%d: %s\n", path, lineno + offset, str)
95
+ if @param["outencoding"] =~ /^EUC$/
96
+ print NKF.nkf("-e", out)
97
+ elsif @param["outencoding"] =~ /^SJIS$/
98
+ print NKF.nkf("-s", out)
99
+ elsif @param["outencoding"] =~ /^JIS$/
100
+ print NKF.nkf("-j", out)
101
+ else
102
+ print out
103
+ end
104
+ end
105
+ end
106
+ }
107
+ end
108
+ end
109
+
110
+ def find_line(lines, re)
111
+ # single line?
112
+ lines.each_with_index do |line, idx|
113
+ return line.gsub(re, '<<<\&>>>'), idx if re =~ line
114
+ end
115
+
116
+ # multiple lines?
117
+ i = 0
118
+ while i < lines.size - 1
119
+ str = lines[i] + lines[i+1]
120
+ return str.gsub(re, '<<<\&>>>'), i if re =~ str
121
+ i += 1
122
+ end
123
+
124
+ raise 'must not happen'
125
+ end
126
+
127
+ def words_re(rc)
128
+ words = []
129
+ nega = []
130
+ File.foreach(rc) do |line|
131
+ next if line[0,1] == '#'
132
+ if / !/ =~ line
133
+ line, n = *line.split(/!/, 2)
134
+ nega.push n.strip
135
+ end
136
+ words.push line.strip
137
+ end
138
+ return Regexp.compile(words.join('|')),
139
+ nega.empty?() ? nil : Regexp.compile(nega.join('|'))
140
+ end
141
+
142
+ def each_paragraph(f)
143
+ $ReVIEW_utils_word_ok = nil
144
+ while line = f.gets
145
+ if @param["inencoding"] =~ /^EUC$/
146
+ line = NKF.nkf("-E -w", line)
147
+ elsif @param["inencoding"] =~ /SJIS$/
148
+ line = NKF.nkf("-S -w", line)
149
+ elsif @param["inencoding"] =~ /^JIS$/
150
+ line = NKF.nkf("-J -w", line)
151
+ else
152
+ line = NKF.nkf("-w", line)
153
+ end
154
+ case line
155
+ when /\A\#@ok\((.*)\)/
156
+ $ReVIEW_utils_word_ok = $1
157
+ when /\A\#@/
158
+ ;
159
+ when %r[\A//caption\{(.*?)//\}]
160
+ yield [$1], f.filename, f.lineno
161
+ when %r<\A//\w.*\{\s*\z>
162
+ while line = f.gets
163
+ break if %r<//\}> === line
164
+ end
165
+ when /\A=/
166
+ yield [line.slice(/\A=+(?:\[.*?\])?\s+(.*)/, 1).strip], f.lineno
167
+ when /\A\s*\z/
168
+ # skip
169
+ else
170
+ buf = [line.strip]
171
+ lineno = f.lineno
172
+ while line = f.gets
173
+ break if line.strip.empty?
174
+ break if %r<\A(?:=|//[\w\}])> =~ line
175
+ next if %r<\A\#@> =~ line
176
+ buf.push line.strip
177
+ end
178
+ yield buf, lineno
179
+ $ReVIEW_utils_word_ok = nil
180
+ end
181
+ end
182
+ end
183
+
184
+ def each_paragraph_line(f, &block)
185
+ each_paragraph(f) do |para, *|
186
+ para.each(&block)
187
+ end
188
+ end
189
+
190
+ sigmain
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # $Id: review-checkdep 3748 2007-12-24 07:06:06Z aamine $
4
+ #
5
+ # Copyright (c) 1999-2007 Minero Aoki
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 'pathname'
14
+
15
+ bindir = Pathname.new(__FILE__).realpath.dirname
16
+ $LOAD_PATH.unshift((bindir + '../lib').realpath)
17
+
18
+ PREDEF_FILE = 'PREDEF'
19
+
20
+ def main
21
+ @provided = parse_predefined()
22
+ @unprovided = {}
23
+ ARGF.each do |line|
24
+ case line
25
+ when /\A\#@require\((.*)\)/
26
+ kw = $1
27
+ unless @provided.key?(kw)
28
+ puts "#{location()}: not provided: #{kw}"
29
+ @unprovided[kw] = location()
30
+ end
31
+ when /\A\#@provide\((.*)\)/
32
+ provide $1
33
+ else
34
+ line.scan(/@<kw>\{(.*?)[,\}]/) do
35
+ provide $1
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ def provide(kw)
42
+ @provided[kw] ||= location()
43
+ if @unprovided[kw]
44
+ reqpos = @unprovided.delete(kw)
45
+ puts "#{location()}: provided now: #{kw} (#{reqpos})"
46
+ end
47
+ end
48
+
49
+ def parse_predefined
50
+ result = {}
51
+ File.foreach(PREDEF_FILE) do |line|
52
+ result[line.strip] = '(predefined)'
53
+ end
54
+ result
55
+ rescue Errno::ENOENT
56
+ return {}
57
+ end
58
+
59
+ def location
60
+ "#{ARGF.filename}:#{ARGF.file.lineno}"
61
+ end
62
+
63
+ main
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # $Id: review-compile 4326 2010-01-12 14:10:17Z kmuto $
4
+ #
5
+ # Copyright (c) 1999-2007 Minero Aoki
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 'pathname'
14
+
15
+ bindir = Pathname.new(__FILE__).realpath.dirname
16
+ $LOAD_PATH.unshift((bindir + '../lib').realpath)
17
+
18
+ require 'review/compiler'
19
+ require 'review/book'
20
+ require 'fileutils'
21
+ require 'optparse'
22
+
23
+ def main
24
+ Signal.trap(:INT) { exit 1 }
25
+ Signal.trap(:PIPE, "IGNORE")
26
+ _main
27
+ rescue Errno::EPIPE
28
+ exit 0
29
+ end
30
+
31
+ def _main
32
+ $KCODE = 'UTF-8' unless defined?(Encoding)
33
+
34
+ mode = :files
35
+ basedir = nil
36
+ if /\Areview2/ =~ File.basename($0)
37
+ target = File.basename($0, '.rb').sub(/review2/, '')
38
+ else
39
+ target = nil
40
+ end
41
+ check_only = false
42
+
43
+ param = {
44
+ "secnolevel" => 2, # for IDGXMLBuilder, EPUBBuilder
45
+ "tableopt" => nil, # for IDGXMLBuilder
46
+ "nolf" => nil, # for IDGXMLBuilder
47
+ "chapref" => nil, # for IDGXMLBuilder
48
+ "inencoding" => "UTF-8",
49
+ "outencoding" => "UTF-8",
50
+ "subdirmode" => nil,
51
+ "stylesheet" => nil, # for EPUBBuilder
52
+ }
53
+
54
+ parser = OptionParser.new
55
+ parser.banner = "Usage: #{File.basename($0)} [--target=FMT]"
56
+ parser.on('--inencoding=ENCODING', 'Set input encoding. (UTF-8, EUC, JIS, and SJIS)') {|enc|
57
+ param["inencoding"] = enc
58
+ }
59
+ parser.on('--outencoding=ENCODING', 'Set output encoding. (UTF-8[default], EUC, JIS, and SJIS)') {|enc|
60
+ param["outencoding"] = enc
61
+ }
62
+ parser.on('-c', '--check', 'Check manuscript') {
63
+ check_only = true
64
+ }
65
+ parser.on('--level=LVL', 'Section level to append number.') {|lvl|
66
+ param["secnolevel"] = lvl.to_i
67
+ }
68
+ parser.on('--nolfinxml', 'Do not insert LF in XML. (idgxml)') {
69
+ param["nolf"] = true
70
+ }
71
+ parser.on('--table=WIDTH', 'Default table width. (idgxml)') {|tbl|
72
+ param["tableopt"] = tbl
73
+ }
74
+ parser.on('--listinfo', 'Append listinfo tag to lists to indicate begin/end. (idgxml)') {
75
+ param["listinfo"] = true
76
+ }
77
+ parser.on('--chapref="before,middle,after"', 'Chapref decoration.') {|cdec|
78
+ param["chapref"] = cdec
79
+ }
80
+ parser.on('--subdirmode', 'Use chapter/id.ext path style to find images.') {
81
+ param["subdirmode"] = true
82
+ }
83
+ parser.on('--stylesheet=file', 'Stylesheet file for EPUB. (epub)') {|file|
84
+ param["stylesheet"] = file
85
+ }
86
+ unless target
87
+ parser.on('--target=FMT', 'Target format.') {|fmt|
88
+ target = fmt
89
+ }
90
+ end
91
+ parser.on('-a', '--all', 'Compile all chapters.') {
92
+ mode = :dir
93
+ basedir = nil
94
+ }
95
+ parser.on('--directory=DIR', 'Compile all chapters in DIR.') {|path|
96
+ mode = :dir
97
+ basedir = path
98
+ }
99
+ parser.on('--help', 'Prints this message and quit.') {
100
+ puts parser.help
101
+ exit 0
102
+ }
103
+ begin
104
+ parser.parse!
105
+ unless target
106
+ if check_only
107
+ target = 'html'
108
+ else
109
+ raise OptionParser::ParseError, "no target given"
110
+ end
111
+ end
112
+ rescue OptionParser::ParseError => err
113
+ error err.message
114
+ $stderr.puts parser.help
115
+ exit 1
116
+ end
117
+
118
+ begin
119
+ compiler = ReVIEW::Compiler.new(load_strategy_class(target, check_only))
120
+ compiler.setParameter(param)
121
+ case mode
122
+ when :files
123
+ if ARGV.empty?
124
+ error 'no input'
125
+ exit 1
126
+ end
127
+ ReVIEW::Chapter.intern_pathes(ARGV).each do |chap|
128
+ chap.setParameter(param)
129
+ result = compiler.compile(chap)
130
+ print result unless check_only
131
+ end
132
+ when :dir
133
+ book = basedir ? ReVIEW::Book.load(basedir) : ReVIEW.book
134
+ book.setParameter(param)
135
+ book.chapters.each do |chap|
136
+ chap.setParameter(param)
137
+ str = compiler.compile(chap)
138
+ write "#{chap.name}#{compiler.strategy.extname}", str unless check_only
139
+ end
140
+ else
141
+ raise "must not happen: #{mode}"
142
+ end
143
+ rescue ReVIEW::ApplicationError => err
144
+ raise if $DEBUG
145
+ error err.message
146
+ exit 1
147
+ end
148
+ end
149
+
150
+ def error(msg)
151
+ $stderr.puts "#{File.basename($0, '.*')}: error: #{msg}"
152
+ end
153
+
154
+ def load_strategy_class(target, strict)
155
+ require "review/#{target}builder"
156
+ ReVIEW.const_get("#{target.upcase}Builder").new(strict)
157
+ end
158
+
159
+ def write(path, str)
160
+ File.open(path, 'w') {|f|
161
+ f.puts str
162
+ }
163
+ end
164
+
165
+ main