review 0.9.0 → 1.0.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/.travis.yml +9 -0
- data/ChangeLog +326 -0
- data/Rakefile +3 -5
- data/VERSION +1 -1
- data/bin/review-compile +50 -50
- data/bin/review-epubmaker +62 -75
- data/bin/review-epubmaker-ng +185 -0
- data/bin/review-index +2 -1
- data/bin/review-pdfmaker +158 -101
- data/bin/review-vol +6 -2
- data/doc/format.rdoc +111 -46
- data/doc/libepubmaker/sample.yaml +90 -0
- data/doc/quickstart.rdoc +188 -0
- data/doc/sample.yaml +8 -0
- data/lib/epubmaker.rb +28 -0
- data/lib/epubmaker/content.rb +82 -0
- data/lib/epubmaker/epubv2.rb +419 -0
- data/lib/epubmaker/epubv3.rb +249 -0
- data/lib/epubmaker/producer.rb +204 -0
- data/lib/epubmaker/resource.rb +66 -0
- data/lib/review.rb +1 -1
- data/lib/review/book.rb +27 -4
- data/lib/review/builder.rb +153 -20
- data/lib/review/compiler.rb +61 -10
- data/lib/review/ewbbuilder.rb +3 -2
- data/lib/review/htmlbuilder.rb +174 -67
- data/lib/review/i18n.rb +30 -0
- data/lib/review/i18n.yaml +23 -0
- data/lib/review/idgxmlbuilder.rb +110 -63
- data/lib/review/index.rb +34 -12
- data/lib/review/latexbuilder.rb +128 -33
- data/lib/review/latexutils.rb +18 -1
- data/lib/review/textbuilder.rb +17 -0
- data/lib/review/tocparser.rb +3 -1
- data/lib/review/tocprinter.rb +1 -0
- data/lib/review/topbuilder.rb +397 -198
- data/review.gemspec +101 -100
- data/test/test_book.rb +27 -0
- data/test/test_epubmaker.rb +507 -0
- data/test/test_helper.rb +8 -0
- data/test/test_htmlbuilder.rb +295 -10
- data/test/test_i18n.rb +64 -0
- data/test/test_idgxmlbuilder.rb +268 -10
- data/test/test_latexbuilder.rb +316 -20
- data/test/test_preprocessor.rb +23 -0
- data/test/test_topbuilder.rb +246 -0
- metadata +46 -53
- data/doc/format.re +0 -505
- data/test/test_index.rb +0 -15
@@ -0,0 +1,66 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# = resource.rb -- Message resources for EPUBMaker.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2010 Kenshi Muto
|
5
|
+
#
|
6
|
+
# This program is free software.
|
7
|
+
# You can distribute or modify this program under the terms of
|
8
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
9
|
+
# For details of the GNU LGPL, see the file "COPYING".
|
10
|
+
#
|
11
|
+
|
12
|
+
module EPUBMaker
|
13
|
+
|
14
|
+
# EPUBMaker::Resource contains message translation resources for EPUBMaker.
|
15
|
+
class Resource
|
16
|
+
# Construct message resource object with using +params+["language"] value.
|
17
|
+
def initialize(params)
|
18
|
+
@hash = nil
|
19
|
+
begin
|
20
|
+
@hash = __send__ params["language"]
|
21
|
+
rescue
|
22
|
+
@hash = __send__ :en
|
23
|
+
end
|
24
|
+
|
25
|
+
@hash.each_pair do |k, v|
|
26
|
+
@hash[k] = params[k] unless params[k].nil?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Return message translation for +key+.
|
31
|
+
def v(key)
|
32
|
+
return @hash[key]
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
# English messages.
|
37
|
+
def en
|
38
|
+
{
|
39
|
+
"toctitle" => "Table of Contents",
|
40
|
+
"covertitle" => "Cover",
|
41
|
+
"titlepagetitle" => "Title Page",
|
42
|
+
"colophontitle" => "Colophon",
|
43
|
+
"c-aut" => "Author",
|
44
|
+
"c-dsr" => "Designer",
|
45
|
+
"c-ill" => "Illustrator",
|
46
|
+
"c-edt" => "Editor",
|
47
|
+
"c-prt" => "Publisher",
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
# Japanese messages.
|
52
|
+
def ja
|
53
|
+
{
|
54
|
+
"toctitle" => "目次",
|
55
|
+
"covertitle" => "表紙",
|
56
|
+
"titlepagetitle" => "権利表記",
|
57
|
+
"colophontitle" => "奥付",
|
58
|
+
"c-aut" => "著 者",
|
59
|
+
"c-dsr" => "デザイン",
|
60
|
+
"c-ill" => "イラスト",
|
61
|
+
"c-edt" => "編 集",
|
62
|
+
"c-prt" => "発行所",
|
63
|
+
}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/review.rb
CHANGED
data/lib/review/book.rb
CHANGED
@@ -32,7 +32,11 @@ module ReVIEW
|
|
32
32
|
def Book.load_default
|
33
33
|
%w( . .. ../.. ).each do |basedir|
|
34
34
|
if File.file?("#{basedir}/CHAPS")
|
35
|
-
|
35
|
+
book = load(basedir)
|
36
|
+
if File.file?("#{basedir}/config.rb")
|
37
|
+
book.instance_variable_set("@parameters", Parameters.load("#{basedir}/config.rb"))
|
38
|
+
end
|
39
|
+
return book
|
36
40
|
end
|
37
41
|
end
|
38
42
|
new('.')
|
@@ -114,7 +118,17 @@ module ReVIEW
|
|
114
118
|
end
|
115
119
|
|
116
120
|
def read_CHAPS
|
117
|
-
|
121
|
+
res = ""
|
122
|
+
File.open("#{@basedir}/#{chapter_file}") do |f|
|
123
|
+
while line = f.gets
|
124
|
+
if /\A#/ =~ line
|
125
|
+
next
|
126
|
+
end
|
127
|
+
line.gsub!(/#.*$/, "")
|
128
|
+
res << line
|
129
|
+
end
|
130
|
+
end
|
131
|
+
res
|
118
132
|
rescue Errno::ENOENT
|
119
133
|
Dir.glob("#{@basedir}/*#{ext()}").sort.join("\n")
|
120
134
|
end
|
@@ -207,7 +221,7 @@ module ReVIEW
|
|
207
221
|
end
|
208
222
|
|
209
223
|
def mkchap(name)
|
210
|
-
name += ext
|
224
|
+
name += ext if File.extname(name) == ""
|
211
225
|
path = "#{@basedir}/#{name}"
|
212
226
|
raise FileNotFound, "file not exist: #{path}" unless File.file?(path)
|
213
227
|
Chapter.new(self, nil, name, path)
|
@@ -310,7 +324,7 @@ module ReVIEW
|
|
310
324
|
@ext = params[:ext] || '.re'
|
311
325
|
@image_dir = params[:image_dir] || 'images'
|
312
326
|
@image_types = unify_exts(params[:image_types] ||
|
313
|
-
%w( eps ai tif tiff png bmp jpg jpeg gif svg ))
|
327
|
+
%w( eps ai tif tiff png bmp jpg jpeg gif svg pdf ))
|
314
328
|
@bib_file = params[:bib_file] || "bib#{@ext}"
|
315
329
|
end
|
316
330
|
|
@@ -424,6 +438,7 @@ module ReVIEW
|
|
424
438
|
@table_index = nil
|
425
439
|
@footnote_index = nil
|
426
440
|
@image_index = nil
|
441
|
+
@icon_index = nil
|
427
442
|
@numberless_image_index = nil
|
428
443
|
@indepimage_index = nil
|
429
444
|
@headline_index = nil
|
@@ -537,6 +552,7 @@ module ReVIEW
|
|
537
552
|
|
538
553
|
def image(id)
|
539
554
|
return image_index()[id] if image_index().has_key?(id)
|
555
|
+
return icon_index()[id] if icon_index().has_key?(id)
|
540
556
|
return numberless_image_index()[id] if numberless_image_index().has_key?(id)
|
541
557
|
indepimage_index()[id]
|
542
558
|
end
|
@@ -555,6 +571,13 @@ module ReVIEW
|
|
555
571
|
@image_index
|
556
572
|
end
|
557
573
|
|
574
|
+
def icon_index
|
575
|
+
@icon_index ||= IconIndex.parse(lines(), id(),
|
576
|
+
"#{book.basedir}#{@book.image_dir}",
|
577
|
+
@book.image_types)
|
578
|
+
@icon_index
|
579
|
+
end
|
580
|
+
|
558
581
|
def indepimage_index
|
559
582
|
@indepimage_index ||=
|
560
583
|
IndepImageIndex.parse(lines(), id(),
|
data/lib/review/builder.rb
CHANGED
@@ -11,10 +11,12 @@ require 'review/index'
|
|
11
11
|
require 'review/exception'
|
12
12
|
require 'stringio'
|
13
13
|
require 'nkf'
|
14
|
+
require 'cgi'
|
14
15
|
|
15
16
|
module ReVIEW
|
16
17
|
|
17
18
|
class Builder
|
19
|
+
CAPTION_TITLES = %w(note memo tip info planning best important security caution term link notice point shoot reference practice expert)
|
18
20
|
|
19
21
|
def pre_paragraph
|
20
22
|
nil
|
@@ -196,21 +198,21 @@ module ReVIEW
|
|
196
198
|
end
|
197
199
|
|
198
200
|
def inline_list(id)
|
199
|
-
"
|
201
|
+
"#{I18n.t("list")}#{@chapter.list(id).number}"
|
200
202
|
rescue KeyError
|
201
203
|
error "unknown list: #{id}"
|
202
204
|
nofunc_text("[UnknownList:#{id}]")
|
203
205
|
end
|
204
206
|
|
205
207
|
def inline_img(id)
|
206
|
-
"
|
208
|
+
"#{I18n.t("image")}#{@chapter.image(id).number}"
|
207
209
|
rescue KeyError
|
208
210
|
error "unknown image: #{id}"
|
209
211
|
nofunc_text("[UnknownImage:#{id}]")
|
210
212
|
end
|
211
213
|
|
212
214
|
def inline_table(id)
|
213
|
-
"
|
215
|
+
"#{I18n.t("table")}#{@chapter.table(id).number}"
|
214
216
|
rescue KeyError
|
215
217
|
error "unknown table: #{id}"
|
216
218
|
nofunc_text("[UnknownTable:#{id}]")
|
@@ -240,6 +242,7 @@ module ReVIEW
|
|
240
242
|
def inline_href(arg)
|
241
243
|
url, label = *arg.scan(/(?:(?:(?:\\\\)*\\,)|[^,\\]+)+/).map(&:lstrip)
|
242
244
|
url = url.gsub(/\\,/, ",").strip
|
245
|
+
label = label.gsub(/\\,/, ",").strip if label
|
243
246
|
compile_href(url, label)
|
244
247
|
end
|
245
248
|
|
@@ -248,12 +251,12 @@ module ReVIEW
|
|
248
251
|
end
|
249
252
|
|
250
253
|
def bibpaper(lines, id, caption)
|
251
|
-
puts "<div>"
|
252
254
|
bibpaper_header id, caption
|
253
255
|
unless lines.empty?
|
256
|
+
puts ""
|
254
257
|
bibpaper_bibpaper id, caption, lines
|
255
258
|
end
|
256
|
-
puts "
|
259
|
+
puts ""
|
257
260
|
end
|
258
261
|
|
259
262
|
def inline_hd(id)
|
@@ -264,28 +267,44 @@ module ReVIEW
|
|
264
267
|
end
|
265
268
|
|
266
269
|
def raw(str)
|
267
|
-
|
270
|
+
if matched = str.match(/\|(.*?)\|(.*)/)
|
271
|
+
builders = matched[1].split(/,/).map{|i| i.gsub(/\s/, '') }
|
272
|
+
c = self.class.to_s.gsub(/ReVIEW::/, '').gsub(/Builder/, '').downcase
|
273
|
+
if builders.include?(c)
|
274
|
+
print matched[2].gsub("\\n", "\n")
|
275
|
+
else
|
276
|
+
""
|
277
|
+
end
|
278
|
+
else
|
279
|
+
warn "It is recommended to set builder(s)."
|
280
|
+
print str.gsub("\\n", "\n")
|
281
|
+
end
|
268
282
|
end
|
269
283
|
|
270
284
|
def find_pathes(id)
|
271
|
-
if ReVIEW.book.param["subdirmode"]
|
272
|
-
re = /\A#{
|
285
|
+
if ReVIEW.book.param["subdirmode"]
|
286
|
+
re = /\A#{id}(?i:#{@chapter.name.join('|')})\z/x
|
273
287
|
entries().select {|ent| re =~ ent }\
|
274
|
-
|
275
|
-
|
276
|
-
|
288
|
+
.sort_by {|ent| @book.image_types.index(File.extname(ent).downcase) }\
|
289
|
+
.map {|ent| "#{@book.basedir}/#{@chapter.name}/#{ent}" }
|
290
|
+
elsif ReVIEW.book.param["singledirmode"]
|
277
291
|
re = /\A#{id}(?i:#{@chapter.name.join('|')})\z/x
|
278
292
|
entries().select {|ent| re =~ ent }\
|
279
|
-
|
280
|
-
|
293
|
+
.sort_by {|ent| @book.image_types.index(File.extname(ent).downcase) }\
|
294
|
+
.map {|ent| "#{@book.basedir}/#{ent}" }
|
295
|
+
else
|
296
|
+
re = /\A#{@chapter.name}-#{id}(?i:#{@book.image_types.join('|')})\z/x
|
297
|
+
entries().select {|ent| re =~ ent }\
|
298
|
+
.sort_by {|ent| @book.image_types.index(File.extname(ent).downcase) }\
|
299
|
+
.map {|ent| "#{@book.basedir}/#{ent}" }
|
281
300
|
end
|
282
301
|
end
|
283
|
-
|
302
|
+
|
284
303
|
def entries
|
285
|
-
if ReVIEW.book.param["subdirmode"]
|
286
|
-
@entries ||= Dir.entries(@book.basedir + @book.image_dir)
|
287
|
-
else
|
304
|
+
if ReVIEW.book.param["subdirmode"]
|
288
305
|
@entries ||= Dir.entries(File.join(@book.basedir + @book.image_dir, @chapter.name))
|
306
|
+
else
|
307
|
+
@entries ||= Dir.entries(@book.basedir + @book.image_dir)
|
289
308
|
end
|
290
309
|
rescue Errno::ENOENT
|
291
310
|
@entries = []
|
@@ -299,11 +318,37 @@ module ReVIEW
|
|
299
318
|
raise ApplicationError, "#{@location}: error: #{msg}"
|
300
319
|
end
|
301
320
|
|
302
|
-
def
|
321
|
+
def handle_metric(str)
|
322
|
+
str
|
323
|
+
end
|
324
|
+
|
325
|
+
def result_metric(array)
|
326
|
+
array.join(',')
|
327
|
+
end
|
328
|
+
|
329
|
+
def parse_metric(type, metric)
|
330
|
+
return "" if metric.nil? || metric.empty?
|
331
|
+
params = metric.split(/,\s*/)
|
332
|
+
results = []
|
333
|
+
params.each do |p|
|
334
|
+
if p =~ /\A.+?::/
|
335
|
+
if p =~ /\A#{type}::/
|
336
|
+
p.sub!(/\A#{type}::/, '')
|
337
|
+
else
|
338
|
+
next
|
339
|
+
end
|
340
|
+
end
|
341
|
+
p = handle_metric(p)
|
342
|
+
results.push(p)
|
343
|
+
end
|
344
|
+
return result_metric(results)
|
345
|
+
end
|
346
|
+
|
347
|
+
def get_chap(chapter = @chapter)
|
303
348
|
if ReVIEW.book.param["secnolevel"] > 0 && !chapter.number.nil? && !chapter.number.to_s.empty?
|
304
|
-
return "#{chapter.number}
|
349
|
+
return "#{chapter.number}"
|
305
350
|
end
|
306
|
-
return
|
351
|
+
return nil
|
307
352
|
end
|
308
353
|
|
309
354
|
def extract_chapter_id(chap_ref)
|
@@ -314,6 +359,94 @@ module ReVIEW
|
|
314
359
|
return [@chapter, chap_ref]
|
315
360
|
end
|
316
361
|
end
|
362
|
+
|
363
|
+
def captionblock(type, lines, caption, specialstyle = nil)
|
364
|
+
raise NotImplementedError
|
365
|
+
end
|
366
|
+
|
367
|
+
CAPTION_TITLES.each do |name|
|
368
|
+
class_eval %Q{
|
369
|
+
def #{name}(lines, caption = nil)
|
370
|
+
captionblock("#{name}", lines, caption)
|
371
|
+
end
|
372
|
+
}
|
373
|
+
end
|
374
|
+
|
375
|
+
def graph(lines, id, command, caption = nil)
|
376
|
+
dir = @book.basedir + @book.image_dir
|
377
|
+
file = "#{@chapter.name}-#{id}.#{image_ext}"
|
378
|
+
if ReVIEW.book.param["subdirmode"]
|
379
|
+
dir = File.join(dir, @chapter.name)
|
380
|
+
file = "#{id}.#{image_ext}"
|
381
|
+
elsif ReVIEW.book.param["singledirmode"]
|
382
|
+
file = "#{id}.#{image_ext}"
|
383
|
+
end
|
384
|
+
file_path = File.join(dir, file)
|
385
|
+
|
386
|
+
line = CGI.unescapeHTML(lines.join("\n"))
|
387
|
+
cmds = {
|
388
|
+
:graphviz => "echo '#{line}' | dot -T#{image_ext} -o#{file_path}",
|
389
|
+
:gnuplot => "echo 'set terminal " +
|
390
|
+
"#{(image_ext == "eps") ? "postscript eps" : image_ext}\n" +
|
391
|
+
" set output \"#{file_path}\"\n#{line}' | gnuplot",
|
392
|
+
:blockdiag => "echo '#{line}' "+
|
393
|
+
"| blockdiag -a -T #{image_ext} -o #{file_path} /dev/stdin",
|
394
|
+
:aafigure => "echo '#{line}' | aafigure -t#{image_ext} -o#{file_path}",
|
395
|
+
}
|
396
|
+
cmd = cmds[command.to_sym]
|
397
|
+
warn cmd
|
398
|
+
system cmd
|
399
|
+
|
400
|
+
image(lines, id, caption)
|
401
|
+
end
|
402
|
+
|
403
|
+
def image_ext
|
404
|
+
raise NotImplementedError
|
405
|
+
end
|
406
|
+
|
407
|
+
def inline_include(file_name)
|
408
|
+
enc = inencoding()
|
409
|
+
compile_inline NKF.nkf("--#{enc}", File.open(file_name).read)
|
410
|
+
end
|
411
|
+
|
412
|
+
def include(file_name)
|
413
|
+
enc = inencoding()
|
414
|
+
File.foreach(file_name) do |line|
|
415
|
+
paragraph([NKF.nkf("--#{enc}", line)])
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
def inencoding
|
420
|
+
if ReVIEW.book.param["inencoding"].nil?
|
421
|
+
enc = "utf8"
|
422
|
+
else
|
423
|
+
# UTF-8, SJIS, EUC => utf8, sjis, euc
|
424
|
+
enc = ReVIEW.book.param["inencoding"].gsub(/-/, '').downcase
|
425
|
+
end
|
426
|
+
end
|
427
|
+
private :inencoding
|
428
|
+
|
429
|
+
def ul_item_begin(lines)
|
430
|
+
ul_item(lines)
|
431
|
+
end
|
432
|
+
|
433
|
+
def ul_item_end
|
434
|
+
end
|
435
|
+
|
436
|
+
def inline_raw(args)
|
437
|
+
if matched = args.match(/\|(.*?)\|(.*)/)
|
438
|
+
builders = matched[1].split(/,/).map{|i| i.gsub(/\s/, '') }
|
439
|
+
c = self.class.to_s.gsub(/ReVIEW::/, '').gsub(/Builder/, '').downcase
|
440
|
+
if builders.include?(c)
|
441
|
+
matched[2].gsub("\\n", "\n")
|
442
|
+
else
|
443
|
+
""
|
444
|
+
end
|
445
|
+
else
|
446
|
+
warn "It is recommended to set builder(s)."
|
447
|
+
args.gsub("\\n", "\n")
|
448
|
+
end
|
449
|
+
end
|
317
450
|
end
|
318
451
|
|
319
452
|
end # module ReVIEW
|
data/lib/review/compiler.rb
CHANGED
@@ -143,6 +143,7 @@ module ReVIEW
|
|
143
143
|
defblock :doorquote, 1
|
144
144
|
defblock :talk, 0
|
145
145
|
defblock :texequation, 0
|
146
|
+
defblock :graph, 1..3
|
146
147
|
|
147
148
|
defblock :address, 0
|
148
149
|
defblock :blockquote, 0
|
@@ -163,11 +164,13 @@ module ReVIEW
|
|
163
164
|
defsingle :label, 1
|
164
165
|
defsingle :raw, 1
|
165
166
|
defsingle :tsize, 1
|
167
|
+
defsingle :include, 1
|
166
168
|
|
167
169
|
definline :chapref
|
168
170
|
definline :chap
|
169
171
|
definline :title
|
170
172
|
definline :img
|
173
|
+
definline :icon
|
171
174
|
definline :list
|
172
175
|
definline :table
|
173
176
|
definline :fn
|
@@ -210,6 +213,8 @@ module ReVIEW
|
|
210
213
|
definline :uchar
|
211
214
|
definline :idx
|
212
215
|
definline :hidx
|
216
|
+
definline :comment
|
217
|
+
definline :include
|
213
218
|
|
214
219
|
private
|
215
220
|
|
@@ -228,8 +233,8 @@ module ReVIEW
|
|
228
233
|
when %r<\A\s*:\s>
|
229
234
|
compile_dlist f
|
230
235
|
when %r<\A//\}>
|
231
|
-
error 'block end seen but not opened'
|
232
236
|
f.gets
|
237
|
+
error 'block end seen but not opened'
|
233
238
|
when %r<\A//[a-z]+>
|
234
239
|
name, args, lines = read_command(f)
|
235
240
|
syntax = syntax_descriptor(name)
|
@@ -266,16 +271,25 @@ module ReVIEW
|
|
266
271
|
caption = m[4].strip
|
267
272
|
index = level - 1
|
268
273
|
if tag
|
269
|
-
|
274
|
+
if tag !~ /\A\//
|
275
|
+
close_current_tagged_section(level)
|
276
|
+
open_tagged_section(tag, level, label, caption)
|
277
|
+
else
|
278
|
+
open_tag = tag[1..-1]
|
279
|
+
prev_tag_info = @tagged_section.pop
|
280
|
+
unless prev_tag_info.first == open_tag
|
281
|
+
raise CompileError, "#{open_tag} is not opened."
|
282
|
+
end
|
283
|
+
@strategy.warn("It is not recommended to use \"#{line.chomp}\"")
|
284
|
+
close_tagged_section(*prev_tag_info)
|
285
|
+
end
|
270
286
|
else
|
271
287
|
if @headline_indexs.size > (index + 1)
|
272
288
|
@headline_indexs = @headline_indexs[0..index]
|
273
289
|
end
|
274
290
|
@headline_indexs[index] = 0 if @headline_indexs[index].nil?
|
275
291
|
@headline_indexs[index] += 1
|
276
|
-
|
277
|
-
close_tagged_section(* @tagged_section.pop)
|
278
|
-
end
|
292
|
+
close_current_tagged_section(level)
|
279
293
|
if ReVIEW.book.param["hdnumberingmode"]
|
280
294
|
caption = @chapter.on_CHAPS? ? "#{@headline_indexs.join('.')} #{caption}" : caption
|
281
295
|
warn "--hdnumberingmode is deprecated. use --level option."
|
@@ -284,6 +298,12 @@ module ReVIEW
|
|
284
298
|
end
|
285
299
|
end
|
286
300
|
|
301
|
+
def close_current_tagged_section(level)
|
302
|
+
while @tagged_section.last and @tagged_section.last[1] >= level
|
303
|
+
close_tagged_section(* @tagged_section.pop)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
287
307
|
def headline(level, label, caption)
|
288
308
|
@strategy.headline level, label, caption
|
289
309
|
end
|
@@ -319,15 +339,46 @@ module ReVIEW
|
|
319
339
|
end
|
320
340
|
|
321
341
|
def compile_ulist(f)
|
322
|
-
|
342
|
+
level = 0
|
323
343
|
f.while_match(/\A\s+\*/) do |line|
|
324
|
-
|
344
|
+
|
345
|
+
buf = [text(line.sub(/\*+/, '').strip)]
|
325
346
|
f.while_match(/\A\s+(?!\*)\S/) do |cont|
|
326
347
|
buf.push text(cont.strip)
|
327
348
|
end
|
328
|
-
|
349
|
+
|
350
|
+
line =~ /\A\s+(\*+)/
|
351
|
+
current_level = $1.size
|
352
|
+
if level == current_level
|
353
|
+
@strategy.ul_item_end
|
354
|
+
# body
|
355
|
+
@strategy.ul_item_begin buf
|
356
|
+
elsif level < current_level # down
|
357
|
+
level_diff = current_level - level
|
358
|
+
level = current_level
|
359
|
+
(1..(level_diff - 1)).to_a.reverse.each do |i|
|
360
|
+
@strategy.ul_begin {i}
|
361
|
+
@strategy.ul_item_begin []
|
362
|
+
end
|
363
|
+
@strategy.ul_begin {level}
|
364
|
+
@strategy.ul_item_begin buf
|
365
|
+
elsif level > current_level # up
|
366
|
+
level_diff = level - current_level
|
367
|
+
level = current_level
|
368
|
+
(1..level_diff).to_a.reverse.each do |i|
|
369
|
+
@strategy.ul_item_end
|
370
|
+
@strategy.ul_end {level + i}
|
371
|
+
@strategy.ul_item_end
|
372
|
+
end
|
373
|
+
# body
|
374
|
+
@strategy.ul_item_begin buf
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
(1..level).to_a.reverse.each do |i|
|
379
|
+
@strategy.ul_item_end
|
380
|
+
@strategy.ul_end {i}
|
329
381
|
end
|
330
|
-
@strategy.ul_end
|
331
382
|
end
|
332
383
|
|
333
384
|
def compile_olist(f)
|
@@ -440,7 +491,7 @@ module ReVIEW
|
|
440
491
|
|
441
492
|
def text(str)
|
442
493
|
return '' if str.empty?
|
443
|
-
words = str.split(/(@<\w+>\{(?:[^\}\\]
|
494
|
+
words = str.split(/(@<\w+>\{(?:[^\}\\]|\\.)*?\})/, -1)
|
444
495
|
words.each do |w|
|
445
496
|
error "`@<xxx>' seen but is not valid inline op: #{w}" if w.scan(/@<\w+>/).size > 1 && !/\A@<raw>/.match(w)
|
446
497
|
end
|