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
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