review 1.5.0 → 1.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.
data/doc/sample.yml CHANGED
@@ -89,7 +89,10 @@ secnolevel: 2
89
89
  # 部番号を表示する見出しレベル(未実装)
90
90
  # part_secnolevel: 1
91
91
 
92
- # EPUB2標準の目次以外に物理目次ファイルを作成するか。省略した場合はnull (作成しない)
92
+ # 本文中に目次ページを作成するか。省略した場合はnull (作成しない)
93
+ # toc: true
94
+
95
+ # EPUB2標準の目次(NCX)以外に物理目次ファイルを作成するか。省略した場合はnull (作成しない)
93
96
  # ePUB3においてはこの設定によらず必ず作成される
94
97
  # mytoc: true
95
98
 
@@ -12,6 +12,7 @@
12
12
  require 'epubmaker/producer'
13
13
  require 'review/i18n'
14
14
  require 'cgi'
15
+ require 'shellwords'
15
16
 
16
17
  module EPUBMaker
17
18
 
@@ -389,10 +390,10 @@ EOT
389
390
  def produce_write_common(basedir, tmpdir)
390
391
  File.open("#{tmpdir}/mimetype", "w") {|f| @producer.mimetype(f) }
391
392
 
392
- Dir.mkdir("#{tmpdir}/META-INF") unless File.exist?("#{tmpdir}/META-INF")
393
+ FileUtils.mkdir_p("#{tmpdir}/META-INF")
393
394
  File.open("#{tmpdir}/META-INF/container.xml", "w") {|f| @producer.container(f) }
394
395
 
395
- Dir.mkdir("#{tmpdir}/OEBPS") unless File.exist?("#{tmpdir}/OEBPS")
396
+ FileUtils.mkdir_p("#{tmpdir}/OEBPS")
396
397
  File.open("#{tmpdir}/OEBPS/#{@producer.params["bookname"]}.opf", "w") {|f| @producer.opf(f) }
397
398
 
398
399
  if File.exist?("#{basedir}/#{@producer.params["cover"]}")
@@ -405,14 +406,14 @@ EOT
405
406
  next if item.file =~ /#/ # skip subgroup
406
407
  fname = "#{basedir}/#{item.file}"
407
408
  raise "#{fname} doesn't exist. Abort." unless File.exist?(fname)
408
- FileUtils.mkdir_p(File.dirname("#{tmpdir}/OEBPS/#{item.file}")) unless File.exist?(File.dirname("#{tmpdir}/OEBPS/#{item.file}"))
409
+ FileUtils.mkdir_p(File.dirname("#{tmpdir}/OEBPS/#{item.file}"))
409
410
  FileUtils.cp(fname, "#{tmpdir}/OEBPS/#{item.file}")
410
411
  end
411
412
  end
412
413
 
413
414
  def export_zip(tmpdir, epubfile)
414
- Dir.chdir(tmpdir) {|d| `#{@producer.params["epubmaker"]["zip_stage1"]} #{epubfile} mimetype` }
415
- Dir.chdir(tmpdir) {|d| `#{@producer.params["epubmaker"]["zip_stage2"]} #{epubfile} META-INF OEBPS #{@producer.params["epubmaker"]["zip_addpath"]}` }
415
+ Dir.chdir(tmpdir) {|d| `#{@producer.params["epubmaker"]["zip_stage1"]} #{epubfile.shellescape} mimetype` }
416
+ Dir.chdir(tmpdir) {|d| `#{@producer.params["epubmaker"]["zip_stage2"]} #{epubfile.shellescape} META-INF OEBPS #{@producer.params["epubmaker"]["zip_addpath"]}` }
416
417
  end
417
418
 
418
419
  def legacy_cover_and_title_file(loadfile, writefile)
@@ -126,7 +126,7 @@ EOT
126
126
 
127
127
  if @producer.params["coverimage"]
128
128
  @producer.contents.each do |item|
129
- if item.media =~ /\Aimage/ && item.file =~ /#{@producer.params["coverimage"]}\Z/
129
+ if item.media =~ /\Aimage/ && File.basename(item.file) == @producer.params["coverimage"]
130
130
  s << %Q[ <item properties="cover-image" id="cover-#{item.id}" href="#{item.file}" media-type="#{item.media}"/>\n]
131
131
  item.id = nil
132
132
  break
@@ -268,7 +268,7 @@ module EPUBMaker
268
268
  end
269
269
  end
270
270
 
271
- @params["htmlversion"] == 5 if @params["epubversion"] >= 3
271
+ @params["htmlversion"] = 5 if @params["epubversion"] >= 3
272
272
 
273
273
  %w[bookname title].each do |k|
274
274
  raise "Key #{k} must have a value. Abort." if @params[k].nil?
@@ -93,7 +93,7 @@ module ReVIEW
93
93
 
94
94
  private
95
95
  def on_FILE?(contents)
96
- contents.lines.map(&:strip).include?(id() + @book.ext())
96
+ contents.lines.map(&:strip).include?("#{id()}#{@book.ext()}")
97
97
  end
98
98
  end
99
99
  end
@@ -57,11 +57,12 @@ module ReVIEW
57
57
  def [](id)
58
58
  @index.fetch(id)
59
59
  rescue
60
- if @index.keys.map{|i| i.split(/\|/) }.flatten. # unfold all ids
60
+ if @index.keys.map{|i| i.split(/\|/).last }.flatten. # unfold all ids
61
61
  reduce(Hash.new(0)){|h, i| h[i] += 1; h}. # number of occurrences
62
62
  select{|k, v| k == id && v > 1 }.present? # detect duplicated
63
63
  raise KeyError, "key '#{id}' is ambiguous for #{self.class}"
64
64
  end
65
+
65
66
  @items.each do |i|
66
67
  if i.id.split(/\|/).include?(id)
67
68
  return i
@@ -104,9 +104,9 @@ module ReVIEW
104
104
  listnum_body lines, lang
105
105
  end
106
106
 
107
- def source(lines, caption)
107
+ def source(lines, caption, lang = nil)
108
108
  source_header caption
109
- source_body lines
109
+ source_body lines, lang
110
110
  end
111
111
 
112
112
  def image(lines, id, caption, metric = nil)
@@ -344,7 +344,7 @@ module ReVIEW
344
344
 
345
345
  def get_chap(chapter = @chapter)
346
346
  if @book.config["secnolevel"] > 0 && !chapter.number.nil? && !chapter.number.to_s.empty?
347
- return "#{chapter.number}"
347
+ return chapter.format_number(nil)
348
348
  end
349
349
  return nil
350
350
  end
@@ -11,7 +11,6 @@
11
11
  require 'review/extentions'
12
12
  require 'review/preprocessor'
13
13
  require 'review/exception'
14
- require 'lineinput'
15
14
  require 'strscan'
16
15
 
17
16
  module ReVIEW
@@ -137,7 +136,7 @@ module ReVIEW
137
136
  defblock :table, 0..2
138
137
  defblock :quote, 0
139
138
  defblock :image, 2..3, true
140
- defblock :source, 0..1
139
+ defblock :source, 0..2
141
140
  defblock :listnum, 2..3
142
141
  defblock :emlistnum, 0..2
143
142
  defblock :bibpaper, 2..3, true
@@ -409,6 +408,7 @@ module ReVIEW
409
408
  @strategy.dt text(f.gets.sub(/\A\s*:/, '').strip)
410
409
  @strategy.dd f.break(/\A(\S|\s*:)/).map {|line| text(line.strip) }
411
410
  f.skip_blank_lines
411
+ f.skip_comment_lines
412
412
  end
413
413
  @strategy.dl_end
414
414
  end
@@ -18,20 +18,20 @@ module ReVIEW
18
18
  include REXML
19
19
 
20
20
  def initialize
21
- @epub = nil
21
+ @producer = nil
22
22
  @tochtmltxt = "toc-html.txt"
23
23
  @buildlogtxt = "build-log.txt"
24
24
  end
25
25
 
26
26
  def log(s)
27
- puts s unless @params["debug"].nil?
27
+ puts s if @params["debug"].present?
28
28
  end
29
29
 
30
30
  def load_yaml(yamlfile)
31
31
  @params = ReVIEW::Configure.values.merge(YAML.load_file(yamlfile)) # FIXME:設定がRe:VIEW側とepubmaker/producer.rb側の2つに分かれて面倒
32
- @epub = Producer.new(@params)
33
- @epub.load(yamlfile)
34
- @params = @epub.params
32
+ @producer = Producer.new(@params)
33
+ @producer.load(yamlfile)
34
+ @params = @producer.params
35
35
  end
36
36
 
37
37
  def produce(yamlfile, bookname=nil)
@@ -42,33 +42,31 @@ module ReVIEW
42
42
 
43
43
  log("Loaded yaml file (#{yamlfile}). I will produce #{bookname}.epub.")
44
44
 
45
- File.unlink("#{bookname}.epub") if File.exist?("#{bookname}.epub")
46
- FileUtils.rm_rf(booktmpname) if @params["debug"] && File.exist?(booktmpname)
45
+ FileUtils.rm_f("#{bookname}.epub")
46
+ FileUtils.rm_rf(booktmpname) if @params["debug"]
47
47
 
48
48
  basetmpdir = Dir.mktmpdir("#{bookname}-", Dir.pwd)
49
49
  begin
50
50
  log("Created first temporary directory as #{basetmpdir}.")
51
51
 
52
- log("Call hook_beforeprocess. (#{@params["epubmaker"]["hook_beforeprocess"]})")
53
- call_hook(@params["epubmaker"]["hook_beforeprocess"], basetmpdir)
52
+ call_hook("hook_beforeprocess", basetmpdir)
54
53
 
54
+ ## copy all files into basetmpdir
55
55
  copy_stylesheet(basetmpdir)
56
56
 
57
57
  copy_frontmatter(basetmpdir)
58
- log("Call hook_afterfrontmatter. (#{@params["epubmaker"]["hook_afterfrontmatter"]})")
59
- call_hook(@params["epubmaker"]["hook_afterfrontmatter"], basetmpdir)
58
+ call_hook("hook_afterfrontmatter", basetmpdir)
60
59
 
61
60
  build_body(basetmpdir, yamlfile)
62
- log("Call hook_afterbody. (#{@params["epubmaker"]["hook_afterbody"]})")
63
- call_hook(@params["epubmaker"]["hook_afterbody"], basetmpdir)
61
+ call_hook("hook_afterbody", basetmpdir)
64
62
 
65
63
  copy_backmatter(basetmpdir)
66
- log("Call hook_afterbackmatter. (#{@params["epubmaker"]["hook_afterbackmatter"]})")
67
- call_hook(@params["epubmaker"]["hook_afterbackmatter"], basetmpdir)
64
+ call_hook("hook_afterbackmatter", basetmpdir)
68
65
 
66
+ ## push contents in basetmpdir into @producer
69
67
  push_contents(basetmpdir)
70
68
 
71
- if !@params["epubmaker"]["verify_target_images"].nil?
69
+ if @params["epubmaker"]["verify_target_images"].present?
72
70
  verify_target_images(basetmpdir)
73
71
  copy_images(@params["imagedir"], basetmpdir)
74
72
  else
@@ -79,24 +77,28 @@ module ReVIEW
79
77
  copy_resources("adv", "#{basetmpdir}/images")
80
78
  copy_resources(@params["fontdir"], "#{basetmpdir}/fonts", @params["font_ext"])
81
79
 
82
- log("Call hook_aftercopyimage. (#{@params["epubmaker"]["hook_aftercopyimage"]})")
83
- call_hook(@params["epubmaker"]["hook_aftercopyimage"], basetmpdir)
80
+ call_hook("hook_aftercopyimage", basetmpdir)
84
81
 
85
- @epub.import_imageinfo("#{basetmpdir}/images", basetmpdir)
86
- @epub.import_imageinfo("#{basetmpdir}/fonts", basetmpdir, @params["font_ext"])
82
+ @producer.import_imageinfo("#{basetmpdir}/images", basetmpdir)
83
+ @producer.import_imageinfo("#{basetmpdir}/fonts", basetmpdir, @params["font_ext"])
87
84
 
88
- epubtmpdir = @params["debug"].nil? ? nil : "#{Dir.pwd}/#{booktmpname}"
89
- Dir.mkdir(booktmpname) unless @params["debug"].nil?
85
+ epubtmpdir = nil
86
+ if @params["debug"].present?
87
+ epubtmpdir = "#{Dir.pwd}/#{booktmpname}"
88
+ Dir.mkdir(epubtmpdir)
89
+ end
90
90
  log("Call ePUB producer.")
91
- @epub.produce("#{bookname}.epub", basetmpdir, epubtmpdir)
91
+ @producer.produce("#{bookname}.epub", basetmpdir, epubtmpdir)
92
92
  log("Finished.")
93
93
  ensure
94
94
  FileUtils.remove_entry_secure basetmpdir if @params["debug"].nil?
95
95
  end
96
96
  end
97
97
 
98
- def call_hook(filename, *params)
99
- if !filename.nil? && File.exist?(filename) && FileTest.executable?(filename)
98
+ def call_hook(hook_name, *params)
99
+ filename = @params["epubmaker"][hook_name]
100
+ log("Call #{hook_name}. (#{filename})")
101
+ if filename.present? && File.exist?(filename) && FileTest.executable?(filename)
100
102
  if ENV["REVIEW_SAFE_MODE"].to_i & 1 > 0
101
103
  warn "hook is prohibited in safe mode. ignored."
102
104
  else
@@ -106,7 +108,7 @@ module ReVIEW
106
108
  end
107
109
 
108
110
  def verify_target_images(basetmpdir)
109
- @epub.contents.each do |content|
111
+ @producer.contents.each do |content|
110
112
  if content.media == "application/xhtml+xml"
111
113
 
112
114
  File.open("#{basetmpdir}/#{content.file}") do |f|
@@ -133,15 +135,15 @@ module ReVIEW
133
135
  def copy_images(resdir, destdir, allow_exts=nil)
134
136
  return nil unless File.exist?(resdir)
135
137
  allow_exts = @params["image_ext"] if allow_exts.nil?
136
- FileUtils.mkdir_p(destdir) unless FileTest.directory?(destdir)
137
- if !@params["epubmaker"]["verify_target_images"].nil?
138
+ FileUtils.mkdir_p(destdir)
139
+ if @params["epubmaker"]["verify_target_images"].present?
138
140
  @params["epubmaker"]["force_include_images"].each do |file|
139
141
  unless File.exist?(file)
140
142
  warn "#{file} is not found, skip." if file !~ /\Ahttp[s]?:/
141
143
  next
142
144
  end
143
145
  basedir = File.dirname(file)
144
- FileUtils.mkdir_p("#{destdir}/#{basedir}") unless FileTest.directory?("#{destdir}/#{basedir}")
146
+ FileUtils.mkdir_p("#{destdir}/#{basedir}")
145
147
  log("Copy #{file} to the temporary directory.")
146
148
  FileUtils.cp(file, "#{destdir}/#{basedir}")
147
149
  end
@@ -153,7 +155,7 @@ module ReVIEW
153
155
  def copy_resources(resdir, destdir, allow_exts=nil)
154
156
  return nil unless File.exist?(resdir)
155
157
  allow_exts = @params["image_ext"] if allow_exts.nil?
156
- FileUtils.mkdir_p(destdir) unless FileTest.directory?(destdir)
158
+ FileUtils.mkdir_p(destdir)
157
159
  recursive_copy_files(resdir, destdir, allow_exts)
158
160
  end
159
161
 
@@ -165,7 +167,7 @@ module ReVIEW
165
167
  recursive_copy_files("#{resdir}/#{fname}", "#{destdir}/#{fname}", allow_exts)
166
168
  else
167
169
  if fname =~ /\.(#{allow_exts.join("|")})\Z/i
168
- FileUtils.mkdir_p(destdir) unless File.exist?(destdir)
170
+ FileUtils.mkdir_p(destdir)
169
171
  log("Copy #{resdir}/#{fname} to the temporary directory.")
170
172
  FileUtils.cp("#{resdir}/#{fname}", destdir)
171
173
  end
@@ -235,7 +237,7 @@ EOT
235
237
  filename = ""
236
238
 
237
239
  chaptype = "body"
238
- if !ispart.nil?
240
+ if ispart.present?
239
241
  chaptype = "part"
240
242
  elsif chap.on_PREDEF?
241
243
  chaptype = "pre"
@@ -243,7 +245,7 @@ EOT
243
245
  chaptype = "post"
244
246
  end
245
247
 
246
- if !ispart.nil?
248
+ if ispart.present?
247
249
  filename = chap.path
248
250
  else
249
251
  filename = Pathname.new(chap.path).relative_path_from(base_path).to_s
@@ -316,7 +318,7 @@ EOT
316
318
  end
317
319
  first = true
318
320
  headlines.each do |headline|
319
- headline["level"] = 0 if !ispart.nil? && headline["level"] == 1
321
+ headline["level"] = 0 if ispart.present? && headline["level"] == 1
320
322
  if first.nil?
321
323
  write_tochtmltxt(basetmpdir, "#{headline["level"]}\t#{filename}##{headline["id"]}\t#{headline["title"]}\tchaptype=#{chaptype}")
322
324
  else
@@ -334,7 +336,7 @@ EOT
334
336
  chaptype = nil
335
337
  properties = nil
336
338
  level, file, title, custom = l.chomp.split("\t")
337
- unless custom.nil?
339
+ if custom.present?
338
340
  # custom setting
339
341
  vars = custom.split(/,\s*/)
340
342
  vars.each do |var|
@@ -361,7 +363,7 @@ EOT
361
363
  if properties.present?
362
364
  hash["properties"] = properties.split(" ")
363
365
  end
364
- @epub.contents.push(Content.new(hash))
366
+ @producer.contents.push(Content.new(hash))
365
367
  end
366
368
  end
367
369
  end
@@ -370,13 +372,13 @@ EOT
370
372
  if @params["stylesheet"].size > 0
371
373
  @params["stylesheet"].each do |sfile|
372
374
  FileUtils.cp(sfile, basetmpdir)
373
- @epub.contents.push(Content.new("file" => sfile))
375
+ @producer.contents.push(Content.new("file" => sfile))
374
376
  end
375
377
  end
376
378
  end
377
379
 
378
380
  def copy_frontmatter(basetmpdir)
379
- FileUtils.cp(@params["cover"], "#{basetmpdir}/#{File.basename(@params["cover"])}") if !@params["cover"].nil? && File.exist?(@params["cover"])
381
+ FileUtils.cp(@params["cover"], "#{basetmpdir}/#{File.basename(@params["cover"])}") if @params["cover"].present? && File.exist?(@params["cover"])
380
382
 
381
383
  if @params["titlepage"]
382
384
  if @params["titlefile"].nil?
@@ -384,17 +386,17 @@ EOT
384
386
  else
385
387
  FileUtils.cp(@params["titlefile"], "#{basetmpdir}/titlepage.#{@params["htmlext"]}")
386
388
  end
387
- write_tochtmltxt(basetmpdir, "1\ttitlepage.#{@params["htmlext"]}\t#{@epub.res.v("titlepagetitle")}\tchaptype=pre")
389
+ write_tochtmltxt(basetmpdir, "1\ttitlepage.#{@params["htmlext"]}\t#{@producer.res.v("titlepagetitle")}\tchaptype=pre")
388
390
  end
389
391
 
390
- if !@params["originaltitlefile"].nil? && File.exist?(@params["originaltitlefile"])
392
+ if @params["originaltitlefile"].present? && File.exist?(@params["originaltitlefile"])
391
393
  FileUtils.cp(@params["originaltitlefile"], "#{basetmpdir}/#{File.basename(@params["originaltitlefile"])}")
392
- write_tochtmltxt(basetmpdir, "1\t#{File.basename(@params["originaltitlefile"])}\t#{@epub.res.v("originaltitle")}\tchaptype=pre")
394
+ write_tochtmltxt(basetmpdir, "1\t#{File.basename(@params["originaltitlefile"])}\t#{@producer.res.v("originaltitle")}\tchaptype=pre")
393
395
  end
394
396
 
395
- if !@params["creditfile"].nil? && File.exist?(@params["creditfile"])
397
+ if @params["creditfile"].present? && File.exist?(@params["creditfile"])
396
398
  FileUtils.cp(@params["creditfile"], "#{basetmpdir}/#{File.basename(@params["creditfile"])}")
397
- write_tochtmltxt(basetmpdir, "1\t#{File.basename(@params["creditfile"])}\t#{@epub.res.v("credittitle")}\tchaptype=pre")
399
+ write_tochtmltxt(basetmpdir, "1\t#{File.basename(@params["creditfile"])}\t#{@producer.res.v("credittitle")}\tchaptype=pre")
398
400
  end
399
401
  end
400
402
 
@@ -427,26 +429,26 @@ EOT
427
429
  def copy_backmatter(basetmpdir)
428
430
  if @params["profile"]
429
431
  FileUtils.cp(@params["profile"], "#{basetmpdir}/#{File.basename(@params["profile"])}")
430
- write_tochtmltxt(basetmpdir, "1\t#{File.basename(@params["profile"])}\t#{@epub.res.v("profiletitle")}\tchaptype=post")
432
+ write_tochtmltxt(basetmpdir, "1\t#{File.basename(@params["profile"])}\t#{@producer.res.v("profiletitle")}\tchaptype=post")
431
433
  end
432
434
 
433
435
  if @params["advfile"]
434
436
  FileUtils.cp(@params["advfile"], "#{basetmpdir}/#{File.basename(@params["advfile"])}")
435
- write_tochtmltxt(basetmpdir, "1\t#{File.basename(@params["advfile"])}\t#{@epub.res.v("advtitle")}\tchaptype=post")
437
+ write_tochtmltxt(basetmpdir, "1\t#{File.basename(@params["advfile"])}\t#{@producer.res.v("advtitle")}\tchaptype=post")
436
438
  end
437
439
 
438
440
  if @params["colophon"]
439
441
  if @params["colophon"].instance_of?(String) # FIXME:このやり方はやめる?
440
442
  FileUtils.cp(@params["colophon"], "#{basetmpdir}/colophon.#{@params["htmlext"]}")
441
443
  else
442
- File.open("#{basetmpdir}/colophon.#{@params["htmlext"]}", "w") {|f| @epub.colophon(f) }
444
+ File.open("#{basetmpdir}/colophon.#{@params["htmlext"]}", "w") {|f| @producer.colophon(f) }
443
445
  end
444
- write_tochtmltxt(basetmpdir, "1\tcolophon.#{@params["htmlext"]}\t#{@epub.res.v("colophontitle")}\tchaptype=post")
446
+ write_tochtmltxt(basetmpdir, "1\tcolophon.#{@params["htmlext"]}\t#{@producer.res.v("colophontitle")}\tchaptype=post")
445
447
  end
446
448
 
447
449
  if @params["backcover"]
448
450
  FileUtils.cp(@params["backcover"], "#{basetmpdir}/#{File.basename(@params["backcover"])}")
449
- write_tochtmltxt(basetmpdir, "1\t#{File.basename(@params["backcover"])}\t#{@epub.res.v("backcovertitle")}\tchaptype=post")
451
+ write_tochtmltxt(basetmpdir, "1\t#{File.basename(@params["backcover"])}\t#{@producer.res.v("backcovertitle")}\tchaptype=post")
450
452
  end
451
453
  end
452
454
 
@@ -515,15 +517,15 @@ EOT
515
517
 
516
518
  def tag_start(name, attrs)
517
519
  if name =~ /\Ah(\d+)/
518
- unless @level.nil?
520
+ if @level.present?
519
521
  raise "#{name}, #{attrs}"
520
522
  end
521
523
  @level = $1.to_i
522
- @id = attrs["id"] if !attrs["id"].nil?
524
+ @id = attrs["id"] if attrs["id"].present?
523
525
  elsif !@level.nil?
524
- if name == "img" && !attrs["alt"].nil?
526
+ if name == "img" && attrs["alt"].present?
525
527
  @content << attrs["alt"]
526
- elsif name == "a" && !attrs["id"].nil?
528
+ elsif name == "a" && attrs["id"].present?
527
529
  @id = attrs["id"]
528
530
  end
529
531
  end
@@ -531,7 +533,7 @@ EOT
531
533
 
532
534
  def tag_end(name)
533
535
  if name =~ /\Ah\d+/
534
- @headlines.push({"level" => @level, "id" => @id, "title" => @content}) unless @id.nil?
536
+ @headlines.push({"level" => @level, "id" => @id, "title" => @content}) if @id.present?
535
537
  @content = ""
536
538
  @level = nil
537
539
  @id = nil
@@ -539,7 +541,7 @@ EOT
539
541
  end
540
542
 
541
543
  def text(text)
542
- unless @level.nil?
544
+ if @level.present?
543
545
  @content << text.gsub("\t", " ") # FIXME:区切り文字
544
546
  end
545
547
  end
@@ -193,6 +193,9 @@ EOT
193
193
 
194
194
  def headline(level, label, caption)
195
195
  prefix, anchor = headline_prefix(level)
196
+ unless prefix.nil?
197
+ prefix = %Q[<span class="secno">#{prefix}</span>]
198
+ end
196
199
  puts '' if level > 1
197
200
  a_id = ""
198
201
  unless anchor.nil?
@@ -453,10 +456,10 @@ EOT
453
456
  puts '</pre>'
454
457
  end
455
458
 
456
- def source(lines, caption = nil)
459
+ def source(lines, caption = nil, lang = nil)
457
460
  puts %Q[<div class="source-code">]
458
461
  source_header caption
459
- source_body caption, lines
462
+ source_body caption, lines, lang
460
463
  puts '</div>'
461
464
  end
462
465
 
@@ -466,11 +469,11 @@ EOT
466
469
  end
467
470
  end
468
471
 
469
- def source_body(id, lines)
472
+ def source_body(id, lines, lang)
470
473
  id ||= ''
471
474
  print %Q[<pre class="source">]
472
475
  body = lines.inject(''){|i, j| i + detab(j) + "\n"}
473
- lexer = File.extname(id).gsub(/\./, '')
476
+ lexer = lang || File.extname(id).gsub(/\./, '')
474
477
  puts highlight(:body => body, :lexer => lexer, :format => 'html')
475
478
  puts '</pre>'
476
479
  end
@@ -942,9 +945,9 @@ QUOTE
942
945
  def inline_hd_chap(chap, id)
943
946
  n = chap.headline_index.number(id)
944
947
  if chap.number and @book.config["secnolevel"] >= n.split('.').size
945
- str = "「#{n} #{compile_inline(chap.headline(id).caption)}"
948
+ str = I18n.t("chapter_quote", "#{n} #{compile_inline(chap.headline(id).caption)}")
946
949
  else
947
- str = "「#{compile_inline(chap.headline(id).caption)}」"
950
+ str = I18n.t("chapter_quote", compile_inline(chap.headline(id).caption))
948
951
  end
949
952
  if @book.config["chapterlink"]
950
953
  anchor = "h"+n.gsub(/\./, "-")