review 0.9.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|