review 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +42 -0
  3. data/README.rdoc +31 -0
  4. data/bin/review-catalog-converter +129 -0
  5. data/bin/review-check +4 -2
  6. data/bin/review-compile +7 -7
  7. data/bin/review-index +4 -3
  8. data/bin/review-init +3 -1
  9. data/bin/review-pdfmaker +2 -258
  10. data/bin/review-vol +2 -2
  11. data/doc/catalog.rdoc +18 -3
  12. data/doc/format.rdoc +2 -3
  13. data/doc/quickstart.rdoc +1 -1
  14. data/lib/epubmaker/epubv2.rb +16 -8
  15. data/lib/epubmaker/epubv3.rb +44 -12
  16. data/lib/epubmaker/producer.rb +4 -2
  17. data/lib/review/book.rb +0 -1
  18. data/lib/review/book/base.rb +72 -35
  19. data/lib/review/book/chapter.rb +8 -12
  20. data/lib/review/book/compilable.rb +8 -8
  21. data/lib/review/book/image_finder.rb +7 -0
  22. data/lib/review/book/index.rb +23 -5
  23. data/lib/review/book/volume.rb +2 -1
  24. data/lib/review/builder.rb +10 -5
  25. data/lib/review/catalog.rb +5 -0
  26. data/lib/review/compiler.rb +1 -1
  27. data/lib/review/configure.rb +12 -0
  28. data/lib/review/epubmaker.rb +13 -7
  29. data/lib/review/htmlbuilder.rb +26 -12
  30. data/lib/review/i18n.rb +2 -2
  31. data/lib/review/i18n.yml +21 -0
  32. data/lib/review/idgxmlbuilder.rb +11 -9
  33. data/lib/review/latexbuilder.rb +3 -2
  34. data/lib/review/{review.tex.erb → layout.tex.erb} +9 -1
  35. data/lib/review/markdownbuilder.rb +126 -4
  36. data/lib/review/pdfmaker.rb +291 -0
  37. data/lib/review/tocparser.rb +6 -5
  38. data/lib/review/tocprinter.rb +5 -2
  39. data/lib/review/version.rb +1 -1
  40. data/review.gemspec +1 -1
  41. data/rubocop-todo.yml +13 -0
  42. data/test/test_book.rb +95 -133
  43. data/test/test_book_chapter.rb +16 -21
  44. data/test/test_builder.rb +12 -7
  45. data/test/test_catalog.rb +15 -3
  46. data/test/test_catalog_converter_cmd.rb +73 -0
  47. data/test/test_epubmaker.rb +5 -5
  48. data/test/test_helper.rb +32 -21
  49. data/test/test_htmlbuilder.rb +219 -192
  50. data/test/test_i18n.rb +46 -19
  51. data/test/test_idgxmlbuilder.rb +177 -182
  52. data/test/test_inaobuilder.rb +1 -2
  53. data/test/test_index.rb +20 -0
  54. data/test/test_latexbuilder.rb +175 -183
  55. data/test/test_markdownbuilder.rb +41 -5
  56. data/test/test_pdfmaker.rb +130 -0
  57. data/test/test_topbuilder.rb +92 -96
  58. metadata +10 -6
  59. data/lib/review/book/parameters.rb +0 -98
  60. data/test/test_book_parameter.rb +0 -42
@@ -31,14 +31,6 @@ module ReVIEW
31
31
  }
32
32
  end
33
33
 
34
- def Chapter.for_stdin
35
- new(nil, nil, '-', nil, $stdin)
36
- end
37
-
38
- def Chapter.for_path(number, path)
39
- new(nil, number, File.basename(path), path)
40
- end
41
-
42
34
  attr_reader :number
43
35
 
44
36
  def initialize(book, number, name, path, io = nil)
@@ -69,7 +61,7 @@ module ReVIEW
69
61
  return "#{@number}"
70
62
  end
71
63
 
72
- if on_POSTDEF?
64
+ if on_APPENDIX?
73
65
  return "#{@number}" if @number < 1 || @number > 27
74
66
 
75
67
  if @book.config["appendix_format"].blank?
@@ -103,15 +95,19 @@ module ReVIEW
103
95
  end
104
96
 
105
97
  def on_CHAPS?
106
- on_FILE?(@book.read_CHAPS())
98
+ on_FILE?(@book.read_CHAPS)
107
99
  end
108
100
 
109
101
  def on_PREDEF?
110
- on_FILE?(@book.read_PREDEF())
102
+ on_FILE?(@book.read_PREDEF)
103
+ end
104
+
105
+ def on_APPENDIX?
106
+ on_FILE?(@book.read_APPENDIX)
111
107
  end
112
108
 
113
109
  def on_POSTDEF?
114
- on_FILE?(@book.read_POSTDEF())
110
+ on_FILE?(@book.read_POSTDEF)
115
111
  end
116
112
 
117
113
  private
@@ -118,29 +118,29 @@ module ReVIEW
118
118
  def numberless_image_index
119
119
  @numberless_image_index ||=
120
120
  NumberlessImageIndex.parse(lines(), id(),
121
- "#{book.basedir}#{@book.image_dir}",
122
- @book.image_types)
121
+ "#{book.basedir}/#{@book.image_dir}",
122
+ @book.image_types, @book.config['builder'])
123
123
  end
124
124
 
125
125
  def image_index
126
126
  @image_index ||= ImageIndex.parse(lines(), id(),
127
- "#{book.basedir}#{@book.image_dir}",
128
- @book.image_types)
127
+ "#{book.basedir}/#{@book.image_dir}",
128
+ @book.image_types, @book.config['builder'])
129
129
  @image_index
130
130
  end
131
131
 
132
132
  def icon_index
133
133
  @icon_index ||= IconIndex.parse(lines(), id(),
134
- "#{book.basedir}#{@book.image_dir}",
135
- @book.image_types)
134
+ "#{book.basedir}/#{@book.image_dir}",
135
+ @book.image_types, @book.config['builder'])
136
136
  @icon_index
137
137
  end
138
138
 
139
139
  def indepimage_index
140
140
  @indepimage_index ||=
141
141
  IndepImageIndex.parse(lines(), id(),
142
- "#{book.basedir}#{@book.image_dir}",
143
- @book.image_types)
142
+ "#{book.basedir}/#{@book.image_dir}",
143
+ @book.image_types, @book.config['builder'])
144
144
  end
145
145
 
146
146
  def bibpaper(id)
@@ -25,6 +25,13 @@ module ReVIEW
25
25
  Dir.glob(File.join(@basedir, "**/*.*"))
26
26
  end
27
27
 
28
+ def add_entry(path)
29
+ unless @entries.include?(path)
30
+ @entries << path
31
+ end
32
+ @entries
33
+ end
34
+
28
35
  def find_path(id)
29
36
  targets = target_list(id)
30
37
  targets.each do |target|
@@ -159,7 +159,7 @@ module ReVIEW
159
159
 
160
160
  attr_reader :image_finder
161
161
 
162
- def initialize(items, chapid, basedir, types)
162
+ def initialize(items, chapid, basedir, types, builder)
163
163
  super items
164
164
  items.each do |i|
165
165
  i.index = self
@@ -169,7 +169,7 @@ module ReVIEW
169
169
  @types = types
170
170
 
171
171
  @image_finder = ReVIEW::Book::ImageFinder.new(basedir, chapid,
172
- ReVIEW.book.config['builder'], types)
172
+ builder, types)
173
173
  end
174
174
 
175
175
  def find_path(id)
@@ -179,7 +179,7 @@ module ReVIEW
179
179
  end
180
180
 
181
181
  class IconIndex < ImageIndex
182
- def initialize(items, chapid, basedir, types)
182
+ def initialize(items, chapid, basedir, types, builder)
183
183
  @items = items
184
184
  @index = {}
185
185
  items.each do |i|
@@ -193,7 +193,7 @@ module ReVIEW
193
193
  @basedir = basedir
194
194
  @types = types
195
195
 
196
- @image_finder = ImageFinder.new(basedir, chapid, ReVIEW.book.config['builder'], types)
196
+ @image_finder = ImageFinder.new(basedir, chapid, builder, types)
197
197
  end
198
198
 
199
199
  def IconIndex.parse(src, *args)
@@ -294,10 +294,28 @@ module ReVIEW
294
294
  items = []
295
295
  indexs = []
296
296
  headlines = []
297
+ inside_column = false
297
298
  src.each do |line|
298
299
  if m = HEADLINE_PATTERN.match(line)
299
- next if m[2] == 'column'
300
+ next if m[1].size > 10 # Ignore too deep index
300
301
  index = m[1].size - 2
302
+
303
+ # column
304
+ if m[2] == 'column'
305
+ inside_column = true
306
+ next
307
+ end
308
+ if m[2] == '/column'
309
+ inside_column = false
310
+ next
311
+ end
312
+ if indexs.present? and indexs[-1] <= index
313
+ inside_column = false
314
+ end
315
+ if inside_column
316
+ next
317
+ end
318
+
301
319
  if index >= 0
302
320
  if indexs.size > (index + 1)
303
321
  indexs = indexs.take(index + 1)
@@ -36,6 +36,7 @@ module ReVIEW
36
36
  @bytes = bytes
37
37
  @chars = chars
38
38
  @lines = lines
39
+ @book = ReVIEW::Book::Base.load_default
39
40
  end
40
41
 
41
42
  attr_reader :bytes
@@ -47,7 +48,7 @@ module ReVIEW
47
48
  end
48
49
 
49
50
  def page
50
- (kbytes.to_f/ReVIEW.book.page_metric.page_per_kbyte).ceil
51
+ (kbytes.to_f/@book.page_metric.page_per_kbyte).ceil
51
52
  end
52
53
 
53
54
  def to_s
@@ -42,9 +42,9 @@ module ReVIEW
42
42
  @chapter = chapter
43
43
  @location = location
44
44
  @output = StringIO.new
45
- @book = ReVIEW.book
45
+ @book = @chapter.book if @chapter.present?
46
46
  @tabwidth = nil
47
- if @book.config && @book.config["tabwidth"]
47
+ if @book && @book.config && @book.config["tabwidth"]
48
48
  @tabwidth = @book.config["tabwidth"]
49
49
  end
50
50
  builder_init_file
@@ -72,6 +72,10 @@ module ReVIEW
72
72
  }
73
73
  end
74
74
 
75
+ def target_name
76
+ self.class.to_s.gsub(/ReVIEW::/, '').gsub(/Builder/, '').downcase
77
+ end
78
+
75
79
  def list(lines, id, caption)
76
80
  begin
77
81
  list_header id, caption
@@ -186,7 +190,7 @@ module ReVIEW
186
190
  end
187
191
 
188
192
  def inline_title(id)
189
- @chapter.env.chapter_index.title(id)
193
+ compile_inline @chapter.env.chapter_index.title(id)
190
194
  rescue KeyError
191
195
  error "unknown chapter: #{id}"
192
196
  nofunc_text("[UnknownChapter:#{id}]")
@@ -273,7 +277,7 @@ module ReVIEW
273
277
  def raw(str)
274
278
  if matched = str.match(/\|(.*?)\|(.*)/)
275
279
  builders = matched[1].split(/,/).map{|i| i.gsub(/\s/, '') }
276
- c = self.class.to_s.gsub(/ReVIEW::/, '').gsub(/Builder/, '').downcase
280
+ c = target_name
277
281
  if builders.include?(c)
278
282
  print matched[2].gsub("\\n", "\n")
279
283
  else
@@ -347,7 +351,7 @@ module ReVIEW
347
351
  end
348
352
 
349
353
  def graph(lines, id, command, caption = nil)
350
- c = self.class.to_s.gsub(/ReVIEW::/, '').gsub(/Builder/, '').downcase
354
+ c = target_name
351
355
  dir = File.join(@book.basedir, @book.image_dir, c)
352
356
  Dir.mkdir(dir) unless File.exist?(dir)
353
357
  file = "#{id}.#{image_ext}"
@@ -366,6 +370,7 @@ module ReVIEW
366
370
  cmd = cmds[command.to_sym]
367
371
  warn cmd
368
372
  system cmd
373
+ @chapter.image_index.image_finder.add_entry(file_path)
369
374
 
370
375
  image(lines, id, caption ||= "")
371
376
  end
@@ -39,6 +39,11 @@ module ReVIEW
39
39
  @yaml["CHAPS"].flatten.reject{|entry| entry.nil?}
40
40
  end
41
41
 
42
+ def appendix
43
+ return "" unless @yaml["APPENDIX"]
44
+ @yaml["APPENDIX"].join("\n")
45
+ end
46
+
42
47
  def postdef
43
48
  return "" unless @yaml["POSTDEF"]
44
49
  @yaml["POSTDEF"].join("\n")
@@ -294,7 +294,7 @@ module ReVIEW
294
294
  @headline_indexs[index] = 0 if @headline_indexs[index].nil?
295
295
  @headline_indexs[index] += 1
296
296
  close_current_tagged_section(level)
297
- if ReVIEW.book.config["hdnumberingmode"]
297
+ if @chapter.book.config["hdnumberingmode"]
298
298
  caption = @chapter.on_CHAPS? ? "#{@headline_indexs.join('.')} #{caption}" : caption
299
299
  warn "--hdnumberingmode is deprecated. use --level option."
300
300
  end
@@ -34,6 +34,18 @@ module ReVIEW
34
34
  "colophon" => nil, # Use colophon
35
35
  "debug" => nil, # debug flag
36
36
  "catalogfile" => 'catalog.yml',
37
+
38
+ "chapter_file" => 'CHAPS',
39
+ "part_file" => 'PART',
40
+ "reject_file" => 'REJECT',
41
+ "predef_file" => 'PREDEF',
42
+ "postdef_file" => 'POSTDEF',
43
+ "page_metric" => ReVIEW::Book::PageMetric.a5,
44
+ "ext" => '.re',
45
+ "image_dir" => 'images',
46
+ "image_types" => %w( .ai .psd .eps .pdf .tif .tiff .png .bmp .jpg .jpeg .gif .svg ),
47
+ "bib_file" => "bib.re",
48
+ "colophon_order" => %w(aut csl trl dsr ill cov edt pbl contact prt),
37
49
  ]
38
50
  end
39
51
  end
@@ -44,7 +44,8 @@ module ReVIEW
44
44
  File.unlink("#{bookname}.epub") if File.exist?("#{bookname}.epub")
45
45
  FileUtils.rm_rf(booktmpname) if @params["debug"] && File.exist?(booktmpname)
46
46
 
47
- Dir.mktmpdir(bookname, Dir.pwd) do |basetmpdir|
47
+ basetmpdir = Dir.mktmpdir("#{bookname}-", Dir.pwd)
48
+ begin
48
49
  log("Created first temporary directory as #{basetmpdir}.")
49
50
 
50
51
  log("Call hook_beforeprocess. (#{@params["hook_beforeprocess"]})")
@@ -88,7 +89,8 @@ module ReVIEW
88
89
  log("Call ePUB producer.")
89
90
  @epub.produce("#{bookname}.epub", basetmpdir, epubtmpdir)
90
91
  log("Finished.")
91
-
92
+ ensure
93
+ FileUtils.remove_entry_secure basetmpdir if @params["debug"].nil?
92
94
  end
93
95
  end
94
96
 
@@ -230,9 +232,13 @@ EOT
230
232
  filename = ""
231
233
 
232
234
  chaptype = "body"
233
- chaptype = "part" unless ispart.nil?
234
- chaptype = "pre" if chap.on_PREDEF?
235
- chaptype = "post" if chap.on_POSTDEF?
235
+ if !ispart.nil?
236
+ chaptype = "part"
237
+ elsif chap.on_PREDEF?
238
+ chaptype = "pre"
239
+ elsif chap.on_APPENDIX?
240
+ chaptype = "post"
241
+ end
236
242
 
237
243
  if !ispart.nil?
238
244
  filename = chap.path
@@ -245,7 +251,7 @@ EOT
245
251
  if chap.on_PREDEF?
246
252
  @precount += 1
247
253
  id = sprintf("pre%02d", @precount)
248
- elsif chap.on_POSTDEF?
254
+ elsif chap.on_APPENDIX?
249
255
  @postcount += 1
250
256
  id = sprintf("post%02d", @postcount)
251
257
  else
@@ -267,7 +273,7 @@ EOT
267
273
  # level = @params["part_secnolevel"]
268
274
  # else
269
275
  # level = @params["pre_secnolevel"] if chap.on_PREDEF?
270
- # level = @params["post_secnolevel"] if chap.on_POSTDEF?
276
+ # level = @params["post_secnolevel"] if chap.on_APPENDIX?
271
277
  # end
272
278
 
273
279
  stylesheet = ""
@@ -63,7 +63,10 @@ module ReVIEW
63
63
  private :builder_init_file
64
64
 
65
65
  def result
66
- layout_file = File.join(@book.basedir, "layouts", "layout.erb")
66
+ layout_file = File.join(@book.basedir, "layouts", "layout.html.erb")
67
+ unless File.exist?(layout_file) # backward compatibility
68
+ layout_file = File.join(@book.basedir, "layouts", "layout.erb")
69
+ end
67
70
  if File.exist?(layout_file)
68
71
  if ENV["REVIEW_SAFE_MODE"].to_i & 4 > 0
69
72
  warn "user's layout is prohibited in safe mode. ignored."
@@ -100,21 +103,21 @@ module ReVIEW
100
103
 
101
104
  # default XHTML header/footer
102
105
  header = <<EOT
103
- <?xml version="1.0" encoding="#{@book.config["outencoding"] || :UTF-8}"?>
106
+ <?xml version="1.0" encoding="#{@book.config["outencoding"] || "UTF-8"}"?>
104
107
  EOT
105
108
  if @book.config["htmlversion"].to_i == 5
106
109
  header += <<EOT
107
110
  <!DOCTYPE html>
108
111
  <html xmlns="http://www.w3.org/1999/xhtml" xmlns:#{xmlns_ops_prefix}="http://www.idpf.org/2007/ops" xml:lang="#{@book.config["language"]}">
109
112
  <head>
110
- <meta charset="#{@book.config["outencoding"] || :UTF-8}" />
113
+ <meta charset="#{@book.config["outencoding"] || "UTF-8"}" />
111
114
  EOT
112
115
  else
113
116
  header += <<EOT
114
117
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
115
118
  <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ops="http://www.idpf.org/2007/ops" xml:lang="#{@book.config["language"]}">
116
119
  <head>
117
- <meta http-equiv="Content-Type" content="text/html;charset=#{@book.config["outencoding"] || :UTF-8}" />
120
+ <meta http-equiv="Content-Type" content="text/html;charset=#{@book.config["outencoding"] || "UTF-8"}" />
118
121
  <meta http-equiv="Content-Style-Type" content="text/css" />
119
122
  EOT
120
123
  end
@@ -502,7 +505,9 @@ EOT
502
505
 
503
506
  def emlist(lines, caption = nil)
504
507
  puts %Q[<div class="emlist-code">]
505
- puts %Q(<p class="caption">#{caption}</p>) unless caption.nil?
508
+ if caption.present?
509
+ puts %Q(<p class="caption">#{compile_inline(caption)}</p>)
510
+ end
506
511
  print %Q[<pre class="emlist">]
507
512
  lines.each do |line|
508
513
  puts detab(line)
@@ -513,7 +518,9 @@ EOT
513
518
 
514
519
  def emlistnum(lines, caption = nil)
515
520
  puts %Q[<div class="emlistnum-code">]
516
- puts %Q(<p class="caption">#{caption}</p>) unless caption.nil?
521
+ if caption.present?
522
+ puts %Q(<p class="caption">#{compile_inline(caption)}</p>)
523
+ end
517
524
  print %Q[<pre class="emlist">]
518
525
  lines.each_with_index do |line, i|
519
526
  puts detab((i+1).to_s.rjust(2) + ": " + line)
@@ -524,7 +531,9 @@ EOT
524
531
 
525
532
  def cmd(lines, caption = nil)
526
533
  puts %Q[<div class="cmd-code">]
527
- puts %Q(<p class="caption">#{caption}</p>) unless caption.nil?
534
+ if caption.present?
535
+ puts %Q(<p class="caption">#{compile_inline(caption)}</p>)
536
+ end
528
537
  print %Q[<pre class="cmd">]
529
538
  lines.each do |line|
530
539
  puts detab(line)
@@ -625,6 +634,7 @@ QUOTE
625
634
  puts %Q[</pre>]
626
635
  image_header id, caption
627
636
  puts %Q[</div>]
637
+ warn "no such image: #{id}"
628
638
  end
629
639
 
630
640
  def image_header(id, caption)
@@ -806,10 +816,11 @@ QUOTE
806
816
  end
807
817
 
808
818
  def inline_title(id)
819
+ title = super
809
820
  if @book.config["chapterlink"]
810
- %Q(<a href="./#{id}#{extname}">#{compile_inline(@chapter.env.chapter_index.title(id))}</a>)
821
+ %Q(<a href="./#{id}#{extname}">#{title}</a>)
811
822
  else
812
- @chapter.env.chapter_index.title(id)
823
+ title
813
824
  end
814
825
  rescue KeyError
815
826
  error "unknown chapter: #{id}"
@@ -899,8 +910,11 @@ QUOTE
899
910
 
900
911
  def inline_m(str)
901
912
  if @book.config["mathml"]
902
- p = MathML::LaTeX::Parser.new(:symbol=>MathML::Symbol::CharacterReference)
903
- %Q[<span class="equation">#{p.parse(str, nil)}</span>]
913
+ require 'math_ml'
914
+ require 'math_ml/symbol/character_reference'
915
+ parser = MathML::LaTeX::Parser.new(
916
+ :symbol => MathML::Symbol::CharacterReference)
917
+ %Q[<span class="equation">#{parser.parse(str, nil)}</span>]
904
918
  else
905
919
  %Q[<span class="equation">#{escape_html(str)}</span>]
906
920
  end
@@ -931,7 +945,7 @@ QUOTE
931
945
  end
932
946
 
933
947
  def inline_bib(id)
934
- %Q(<a href=".#{@book.bib_file.gsub(/re\Z/, "html")}#bib-#{id}">[#{@chapter.bibpaper(id).number}]</a>)
948
+ %Q(<a href="#{@book.bib_file.gsub(/re\Z/, "html")}#bib-#{normalize_id(id)}">[#{@chapter.bibpaper(id).number}]</a>)
935
949
  end
936
950
 
937
951
  def inline_hd_chap(chap, id)
@@ -4,9 +4,9 @@ require 'yaml'
4
4
  module ReVIEW
5
5
  class I18n
6
6
  def self.setup
7
- lfile = File.expand_path "locale.yml", ENV["PWD"]
7
+ lfile = File.expand_path "locale.yml", Dir.pwd
8
8
  # backward compatibility
9
- lfile = File.expand_path "locale.yaml", ENV["PWD"] unless File.exist?(lfile)
9
+ lfile = File.expand_path "locale.yaml", Dir.pwd unless File.exist?(lfile)
10
10
  user_i18n = YAML.load_file(lfile)
11
11
  I18n.i18n user_i18n["locale"], user_i18n
12
12
  rescue