review 2.5.0 → 3.0.0.preview1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +28 -10
- data/.travis.yml +11 -2
- data/NEWS.ja.md +89 -17
- data/NEWS.md +92 -0
- data/README.md +1 -1
- data/Rakefile +0 -13
- data/bin/review-catalog-converter +83 -37
- data/bin/review-check +17 -5
- data/bin/review-compile +1 -1
- data/bin/review-index +6 -0
- data/bin/review-init +3 -155
- data/bin/review-preproc +0 -5
- data/bin/review-validate +21 -7
- data/bin/review-vol +13 -5
- data/doc/config.yml.sample +12 -7
- data/doc/config.yml.sample-simple +1 -1
- data/doc/format.ja.md +39 -3
- data/doc/format.md +39 -3
- data/doc/format_idg.ja.md +0 -4
- data/doc/pdfmaker.ja.md +1 -1
- data/doc/pdfmaker.md +1 -1
- data/doc/sample.css +7 -0
- data/lib/epubmaker/content.rb +31 -12
- data/lib/epubmaker/epubcommon.rb +10 -3
- data/lib/epubmaker/epubv2.rb +11 -3
- data/lib/epubmaker/epubv3.rb +11 -3
- data/lib/epubmaker/producer.rb +55 -20
- data/lib/review/book/base.rb +63 -48
- data/lib/review/book/chapter.rb +19 -7
- data/lib/review/book/compilable.rb +5 -20
- data/lib/review/book/image_finder.rb +10 -3
- data/lib/review/book/index.rb +30 -9
- data/lib/review/book/part.rb +9 -6
- data/lib/review/book.rb +0 -14
- data/lib/review/builder.rb +110 -18
- data/lib/review/catalog.rb +24 -4
- data/lib/review/compiler.rb +3 -1
- data/lib/review/configure.rb +43 -9
- data/lib/review/epubmaker/reviewheaderlistener.rb +57 -0
- data/lib/review/epubmaker.rb +129 -85
- data/lib/review/htmlbuilder.rb +76 -58
- data/lib/review/htmlutils.rb +20 -13
- data/lib/review/i18n.rb +6 -2
- data/lib/review/idgxmlbuilder.rb +52 -41
- data/lib/review/init.rb +194 -0
- data/lib/review/latexbuilder.rb +118 -34
- data/lib/review/latexutils.rb +5 -5
- data/lib/review/logger.rb +2 -1
- data/lib/review/makerhelper.rb +1 -1
- data/lib/review/markdownbuilder.rb +66 -6
- data/lib/review/md2inaobuilder.rb +2 -2
- data/lib/review/pdfmaker.rb +74 -22
- data/lib/review/plaintextbuilder.rb +8 -4
- data/lib/review/preprocessor.rb +14 -17
- data/lib/review/sec_counter.rb +8 -2
- data/lib/review/textmaker.rb +2 -2
- data/lib/review/textutils.rb +9 -2
- data/lib/review/tocparser.rb +7 -4
- data/lib/review/tocprinter.rb +3 -1
- data/lib/review/version.rb +1 -1
- data/lib/review/webmaker.rb +19 -7
- data/lib/review/webtocprinter.rb +8 -4
- data/review.gemspec +4 -3
- data/templates/latex/config.erb +84 -0
- data/templates/latex/layout.tex.erb +76 -361
- data/templates/latex/review-jlreq/README.md +22 -0
- data/templates/latex/review-jlreq/review-base.sty +178 -0
- data/templates/latex/review-jlreq/review-custom.sty +1 -0
- data/templates/latex/review-jlreq/review-jlreq.cls +141 -0
- data/templates/latex/review-jlreq/review-style.sty +149 -0
- data/templates/latex/review-jlreq/reviewmacro.sty +8 -0
- data/templates/latex/review-jsbook/jumoline.sty +310 -0
- data/templates/latex/review-jsbook/plistings.sty +326 -0
- data/templates/latex/review-jsbook/review-base.sty +405 -0
- data/templates/latex/review-jsbook/review-custom.sty +1 -0
- data/templates/latex/review-jsbook/review-style.sty +38 -0
- data/templates/latex/review-jsbook/reviewmacro.sty +8 -0
- data/templates/latex-compat2/layout.tex.erb +387 -0
- data/test/assets/test_template.tex +105 -235
- data/test/assets/test_template_backmatter.tex +133 -14
- data/test/book_test_helper.rb +1 -1
- data/test/run_test.rb +2 -0
- data/test/sample-book/src/Rakefile +11 -6
- data/test/sample-book/src/config.yml +2 -2
- data/test/sample-book/src/sty/reviewmacro.sty +1 -39
- data/test/sample-book/src/style.css +6 -0
- data/test/syntax-book/config.yml +1 -1
- data/test/test_book.rb +13 -16
- data/test/test_book_chapter.rb +4 -10
- data/test/test_book_part.rb +4 -3
- data/test/test_catalog.rb +15 -4
- data/test/test_helper.rb +2 -2
- data/test/test_htmlbuilder.rb +78 -10
- data/test/test_htmlutils.rb +12 -5
- data/test/test_idgxmlbuilder.rb +1 -1
- data/test/test_latexbuilder.rb +94 -49
- data/test/test_latexbuilder_v2.rb +1077 -0
- data/test/test_logger.rb +20 -0
- data/test/test_markdownbuilder.rb +10 -0
- data/test/test_pdfmaker.rb +6 -7
- data/test/test_plaintextbuilder.rb +1 -1
- data/test/test_review_ext.rb +0 -1
- data/test/test_rstbuilder.rb +1 -1
- data/test/test_topbuilder.rb +19 -7
- data/test/test_webtocprinter.rb +14 -14
- data/{test/sample-book/src/vendor → vendor}/jumoline/README +0 -0
- data/{test/sample-book/src/vendor → vendor}/jumoline/jumoline.dtx +0 -0
- data/{test/sample-book/src/vendor → vendor}/jumoline/jumoline.ins +0 -0
- data/{test/sample-book/src/vendor → vendor}/jumoline/lppl.txt +0 -0
- data/vendor/plistings/.gitignore +9 -0
- data/vendor/plistings/LICENSE +21 -0
- data/vendor/plistings/README.md +18 -0
- data/vendor/plistings/plistings.sty +326 -0
- data/vendor/plistings/test1.tex +174 -0
- data/vendor/plistings/test2.tex +54 -0
- metadata +48 -19
- data/lib/review/unfold.rb +0 -129
- data/test/CHAPS +0 -2
- data/test/bib.re +0 -13
- data/test/test.re +0 -43
data/lib/review/epubmaker.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2010-
|
1
|
+
# Copyright (c) 2010-2018 Kenshi Muto and Masayoshi Takahashi
|
2
2
|
#
|
3
3
|
# This program is free software.
|
4
4
|
# You can distribute or modify this program under the terms of
|
@@ -22,6 +22,7 @@ require 'review/yamlloader'
|
|
22
22
|
require 'rexml/document'
|
23
23
|
require 'rexml/streamlistener'
|
24
24
|
require 'epubmaker'
|
25
|
+
require 'review/epubmaker/reviewheaderlistener'
|
25
26
|
|
26
27
|
module ReVIEW
|
27
28
|
class EPUBMaker
|
@@ -45,7 +46,9 @@ module ReVIEW
|
|
45
46
|
end
|
46
47
|
|
47
48
|
def log(s)
|
48
|
-
|
49
|
+
if @config['debug'].present?
|
50
|
+
puts s
|
51
|
+
end
|
49
52
|
end
|
50
53
|
|
51
54
|
def load_yaml(yamlfile)
|
@@ -66,7 +69,9 @@ module ReVIEW
|
|
66
69
|
def build_path
|
67
70
|
if @config['debug']
|
68
71
|
path = File.expand_path("#{@config['bookname']}-epub", Dir.pwd)
|
69
|
-
|
72
|
+
if File.exist?(path)
|
73
|
+
FileUtils.rm_rf(path, secure: true)
|
74
|
+
end
|
70
75
|
Dir.mkdir(path)
|
71
76
|
path
|
72
77
|
else
|
@@ -77,7 +82,7 @@ module ReVIEW
|
|
77
82
|
def produce(yamlfile, bookname = nil)
|
78
83
|
load_yaml(yamlfile)
|
79
84
|
I18n.setup(@config['language'])
|
80
|
-
bookname
|
85
|
+
bookname ||= @config['bookname']
|
81
86
|
booktmpname = "#{bookname}-epub"
|
82
87
|
|
83
88
|
begin
|
@@ -88,9 +93,13 @@ module ReVIEW
|
|
88
93
|
log("Loaded yaml file (#{yamlfile}). I will produce #{bookname}.epub.")
|
89
94
|
|
90
95
|
FileUtils.rm_f("#{bookname}.epub")
|
91
|
-
|
96
|
+
if @config['debug']
|
97
|
+
FileUtils.rm_rf(booktmpname)
|
98
|
+
end
|
92
99
|
math_dir = "./#{@config['imagedir']}/_review_math"
|
93
|
-
|
100
|
+
if @config['imgmath'] && Dir.exist?(math_dir)
|
101
|
+
FileUtils.rm_rf(math_dir)
|
102
|
+
end
|
94
103
|
|
95
104
|
basetmpdir = build_path
|
96
105
|
begin
|
@@ -162,17 +171,22 @@ module ReVIEW
|
|
162
171
|
|
163
172
|
def verify_target_images(basetmpdir)
|
164
173
|
@producer.contents.each do |content|
|
165
|
-
|
174
|
+
case content.media
|
175
|
+
when 'application/xhtml+xml'
|
166
176
|
File.open("#{basetmpdir}/#{content.file}") do |f|
|
167
177
|
Document.new(File.new(f)).each_element('//img') do |e|
|
168
178
|
@config['epubmaker']['force_include_images'].push(e.attributes['src'])
|
169
|
-
|
179
|
+
if e.attributes['src'] =~ /svg\Z/i
|
180
|
+
content.properties.push('svg')
|
181
|
+
end
|
170
182
|
end
|
171
183
|
end
|
172
|
-
|
184
|
+
when 'text/css'
|
173
185
|
File.open("#{basetmpdir}/#{content.file}") do |f|
|
174
186
|
f.each_line do |l|
|
175
|
-
l.scan(/url\((.+?)\)/)
|
187
|
+
l.scan(/url\((.+?)\)/) do |_m|
|
188
|
+
@config['epubmaker']['force_include_images'].push($1.strip)
|
189
|
+
end
|
176
190
|
end
|
177
191
|
end
|
178
192
|
end
|
@@ -182,12 +196,14 @@ module ReVIEW
|
|
182
196
|
|
183
197
|
def copy_images(resdir, destdir, allow_exts = nil)
|
184
198
|
return nil unless File.exist?(resdir)
|
185
|
-
allow_exts
|
199
|
+
allow_exts ||= @config['image_ext']
|
186
200
|
FileUtils.mkdir_p(destdir)
|
187
201
|
if @config['epubmaker']['verify_target_images'].present?
|
188
202
|
@config['epubmaker']['force_include_images'].each do |file|
|
189
203
|
unless File.exist?(file)
|
190
|
-
|
204
|
+
if file !~ /\Ahttp[s]?:/
|
205
|
+
warn "#{file} is not found, skip."
|
206
|
+
end
|
191
207
|
next
|
192
208
|
end
|
193
209
|
basedir = File.dirname(file)
|
@@ -202,7 +218,7 @@ module ReVIEW
|
|
202
218
|
|
203
219
|
def copy_resources(resdir, destdir, allow_exts = nil)
|
204
220
|
return nil unless File.exist?(resdir)
|
205
|
-
allow_exts
|
221
|
+
allow_exts ||= @config['image_ext']
|
206
222
|
FileUtils.mkdir_p(destdir)
|
207
223
|
recursive_copy_files(resdir, destdir, allow_exts)
|
208
224
|
end
|
@@ -252,7 +268,9 @@ module ReVIEW
|
|
252
268
|
htmlfile = "part_#{part.number}.#{@config['htmlext']}"
|
253
269
|
build_part(part, basetmpdir, htmlfile)
|
254
270
|
title = ReVIEW::I18n.t('part', part.number)
|
255
|
-
|
271
|
+
if part.name.strip.present?
|
272
|
+
title += ReVIEW::I18n.t('chapter_postfix') + part.name.strip
|
273
|
+
end
|
256
274
|
@htmltoc.add_item(0, htmlfile, title, chaptype: 'part')
|
257
275
|
write_buildlogtxt(basetmpdir, htmlfile, '')
|
258
276
|
end
|
@@ -309,7 +327,7 @@ module ReVIEW
|
|
309
327
|
Pathname.new(chap.path).relative_path_from(base_path).to_s
|
310
328
|
end
|
311
329
|
|
312
|
-
id = filename.sub(/\.re\Z/, '')
|
330
|
+
id = File.basename(filename).sub(/\.re\Z/, '')
|
313
331
|
|
314
332
|
if @config['epubmaker']['rename_for_legacy'] && ispart.nil?
|
315
333
|
if chap.on_predef?
|
@@ -376,15 +394,29 @@ module ReVIEW
|
|
376
394
|
htmlio = File.new(path)
|
377
395
|
Document.parse_stream(htmlio, ReVIEWHeaderListener.new(headlines))
|
378
396
|
properties = detect_properties(path)
|
379
|
-
|
380
|
-
|
397
|
+
if properties.present?
|
398
|
+
prop_str = ',properties=' + properties.join(' ')
|
399
|
+
else
|
400
|
+
prop_str = ''
|
401
|
+
end
|
381
402
|
first = true
|
382
403
|
headlines.each do |headline|
|
383
|
-
|
404
|
+
if ispart.present? && headline['level'] == 1
|
405
|
+
headline['level'] = 0
|
406
|
+
end
|
384
407
|
if first.nil?
|
385
|
-
@htmltoc.add_item(headline['level'],
|
408
|
+
@htmltoc.add_item(headline['level'],
|
409
|
+
filename + '#' + headline['id'],
|
410
|
+
headline['title'],
|
411
|
+
{ chaptype: chaptype,
|
412
|
+
notoc: headline['notoc'] })
|
386
413
|
else
|
387
|
-
@htmltoc.add_item(headline['level'],
|
414
|
+
@htmltoc.add_item(headline['level'],
|
415
|
+
filename,
|
416
|
+
headline['title'],
|
417
|
+
{ force_include: true,
|
418
|
+
chaptype: chaptype + prop_str,
|
419
|
+
notoc: headline['notoc'] })
|
388
420
|
first = nil
|
389
421
|
end
|
390
422
|
end
|
@@ -396,10 +428,19 @@ module ReVIEW
|
|
396
428
|
next if level.to_i > @config['toclevel'] && args[:force_include].nil?
|
397
429
|
log("Push #{file} to ePUB contents.")
|
398
430
|
|
399
|
-
hash = { 'file' => file,
|
400
|
-
|
401
|
-
|
402
|
-
|
431
|
+
hash = { 'file' => file,
|
432
|
+
'level' => level.to_i,
|
433
|
+
'title' => title,
|
434
|
+
'chaptype' => args[:chaptype] }
|
435
|
+
if args[:id].present?
|
436
|
+
hash['id'] = args[:id]
|
437
|
+
end
|
438
|
+
if args[:properties].present?
|
439
|
+
hash['properties'] = args[:properties].split(' ')
|
440
|
+
end
|
441
|
+
if args[:notoc].present?
|
442
|
+
hash['notoc'] = args[:notoc]
|
443
|
+
end
|
403
444
|
@producer.contents.push(Content.new(hash))
|
404
445
|
end
|
405
446
|
end
|
@@ -413,25 +454,40 @@ module ReVIEW
|
|
413
454
|
end
|
414
455
|
|
415
456
|
def copy_frontmatter(basetmpdir)
|
416
|
-
|
457
|
+
if @config['cover'].present? && File.exist?(@config['cover'])
|
458
|
+
FileUtils.cp(@config['cover'],
|
459
|
+
"#{basetmpdir}/#{File.basename(@config['cover'])}")
|
460
|
+
end
|
417
461
|
|
418
462
|
if @config['titlepage']
|
419
463
|
if @config['titlefile'].nil?
|
420
464
|
build_titlepage(basetmpdir, "titlepage.#{@config['htmlext']}")
|
421
465
|
else
|
422
|
-
FileUtils.cp(@config['titlefile'],
|
466
|
+
FileUtils.cp(@config['titlefile'],
|
467
|
+
"#{basetmpdir}/titlepage.#{@config['htmlext']}")
|
423
468
|
end
|
424
|
-
@htmltoc.add_item(1,
|
469
|
+
@htmltoc.add_item(1,
|
470
|
+
"titlepage.#{@config['htmlext']}",
|
471
|
+
@producer.res.v('titlepagetitle'),
|
472
|
+
chaptype: 'pre')
|
425
473
|
end
|
426
474
|
|
427
475
|
if @config['originaltitlefile'].present? && File.exist?(@config['originaltitlefile'])
|
428
|
-
FileUtils.cp(@config['originaltitlefile'],
|
429
|
-
|
476
|
+
FileUtils.cp(@config['originaltitlefile'],
|
477
|
+
"#{basetmpdir}/#{File.basename(@config['originaltitlefile'])}")
|
478
|
+
@htmltoc.add_item(1,
|
479
|
+
File.basename(@config['originaltitlefile']),
|
480
|
+
@producer.res.v('originaltitle'),
|
481
|
+
chaptype: 'pre')
|
430
482
|
end
|
431
483
|
|
432
484
|
if @config['creditfile'].present? && File.exist?(@config['creditfile'])
|
433
|
-
FileUtils.cp(@config['creditfile'],
|
434
|
-
|
485
|
+
FileUtils.cp(@config['creditfile'],
|
486
|
+
"#{basetmpdir}/#{File.basename(@config['creditfile'])}")
|
487
|
+
@htmltoc.add_item(1,
|
488
|
+
File.basename(@config['creditfile']),
|
489
|
+
@producer.res.v('credittitle'),
|
490
|
+
chaptype: 'pre')
|
435
491
|
end
|
436
492
|
|
437
493
|
true
|
@@ -444,9 +500,15 @@ module ReVIEW
|
|
444
500
|
@body = ''
|
445
501
|
@body << %Q(<div class="titlepage">\n)
|
446
502
|
@body << %Q(<h1 class="tp-title">#{CGI.escapeHTML(@config.name_of('booktitle'))}</h1>\n)
|
447
|
-
|
448
|
-
|
449
|
-
|
503
|
+
if @config['subtitle']
|
504
|
+
@body << %Q(<h2 class="tp-subtitle">#{CGI.escapeHTML(@config.name_of('subtitle'))}</h2>\n)
|
505
|
+
end
|
506
|
+
if @config['aut']
|
507
|
+
@body << %Q(<h2 class="tp-author">#{CGI.escapeHTML(@config.names_of('aut').join(ReVIEW::I18n.t('names_splitter')))}</h2>\n)
|
508
|
+
end
|
509
|
+
if @config['pbl']
|
510
|
+
@body << %Q(<h3 class="tp-publisher">#{CGI.escapeHTML(@config.names_of('pbl').join(ReVIEW::I18n.t('names_splitter')))}</h3>\n)
|
511
|
+
end
|
450
512
|
@body << '</div>'
|
451
513
|
|
452
514
|
@language = @producer.config['language']
|
@@ -459,34 +521,55 @@ module ReVIEW
|
|
459
521
|
|
460
522
|
def copy_backmatter(basetmpdir)
|
461
523
|
if @config['profile']
|
462
|
-
FileUtils.cp(@config['profile'],
|
463
|
-
|
524
|
+
FileUtils.cp(@config['profile'],
|
525
|
+
"#{basetmpdir}/#{File.basename(@config['profile'])}")
|
526
|
+
@htmltoc.add_item(1,
|
527
|
+
File.basename(@config['profile']),
|
528
|
+
@producer.res.v('profiletitle'),
|
529
|
+
chaptype: 'post')
|
464
530
|
end
|
465
531
|
|
466
532
|
if @config['advfile']
|
467
|
-
FileUtils.cp(@config['advfile'],
|
468
|
-
|
533
|
+
FileUtils.cp(@config['advfile'],
|
534
|
+
"#{basetmpdir}/#{File.basename(@config['advfile'])}")
|
535
|
+
@htmltoc.add_item(1,
|
536
|
+
File.basename(@config['advfile']),
|
537
|
+
@producer.res.v('advtitle'),
|
538
|
+
chaptype: 'post')
|
469
539
|
end
|
470
540
|
|
471
541
|
if @config['colophon']
|
472
542
|
if @config['colophon'].is_a?(String) # FIXME: should let obsolete this style?
|
473
|
-
FileUtils.cp(@config['colophon'],
|
543
|
+
FileUtils.cp(@config['colophon'],
|
544
|
+
"#{basetmpdir}/colophon.#{@config['htmlext']}")
|
474
545
|
else
|
475
|
-
|
546
|
+
filename = "#{basetmpdir}/colophon.#{@config['htmlext']}"
|
547
|
+
File.open(filename, 'w') do |f|
|
548
|
+
@producer.colophon(f)
|
549
|
+
end
|
476
550
|
end
|
477
|
-
@htmltoc.add_item(1,
|
551
|
+
@htmltoc.add_item(1,
|
552
|
+
"colophon.#{@config['htmlext']}",
|
553
|
+
@producer.res.v('colophontitle'),
|
554
|
+
chaptype: 'post')
|
478
555
|
end
|
479
556
|
|
480
557
|
if @config['backcover']
|
481
|
-
FileUtils.cp(@config['backcover'],
|
482
|
-
|
558
|
+
FileUtils.cp(@config['backcover'],
|
559
|
+
"#{basetmpdir}/#{File.basename(@config['backcover'])}")
|
560
|
+
@htmltoc.add_item(1,
|
561
|
+
File.basename(@config['backcover']),
|
562
|
+
@producer.res.v('backcovertitle'),
|
563
|
+
chaptype: 'post')
|
483
564
|
end
|
484
565
|
|
485
566
|
true
|
486
567
|
end
|
487
568
|
|
488
569
|
def write_buildlogtxt(basetmpdir, htmlfile, reviewfile)
|
489
|
-
File.open("#{basetmpdir}/#{@buildlogtxt}", 'a')
|
570
|
+
File.open("#{basetmpdir}/#{@buildlogtxt}", 'a') do |f|
|
571
|
+
f.puts "#{htmlfile},#{reviewfile}"
|
572
|
+
end
|
490
573
|
end
|
491
574
|
|
492
575
|
def check_image_size(basetmpdir, maxpixels, allow_exts = nil)
|
@@ -498,7 +581,8 @@ module ReVIEW
|
|
498
581
|
require 'find'
|
499
582
|
allow_exts ||= @config['image_ext']
|
500
583
|
|
501
|
-
|
584
|
+
pat = '\\.(' + allow_exts.delete_if { |t| %w[ttf woff otf].member?(t.downcase) }.join('|') + ')'
|
585
|
+
extre = Regexp.new(pat, Regexp::IGNORECASE)
|
502
586
|
Find.find(basetmpdir) do |fname|
|
503
587
|
next unless fname.match(extre)
|
504
588
|
img = ImageSize.path(fname)
|
@@ -511,45 +595,5 @@ module ReVIEW
|
|
511
595
|
|
512
596
|
true
|
513
597
|
end
|
514
|
-
|
515
|
-
class ReVIEWHeaderListener
|
516
|
-
include REXML::StreamListener
|
517
|
-
def initialize(headlines)
|
518
|
-
@level = nil
|
519
|
-
@content = ''
|
520
|
-
@headlines = headlines
|
521
|
-
end
|
522
|
-
|
523
|
-
def tag_start(name, attrs)
|
524
|
-
if name =~ /\Ah(\d+)/
|
525
|
-
raise "#{name}, #{attrs}" if @level.present?
|
526
|
-
@level = $1.to_i
|
527
|
-
@id = attrs['id'] if attrs['id'].present?
|
528
|
-
@notoc = attrs['notoc'] if attrs['notoc'].present?
|
529
|
-
elsif !@level.nil?
|
530
|
-
if name == 'img' && attrs['alt'].present?
|
531
|
-
@content << attrs['alt']
|
532
|
-
elsif name == 'a' && attrs['id'].present?
|
533
|
-
@id = attrs['id']
|
534
|
-
end
|
535
|
-
end
|
536
|
-
end
|
537
|
-
|
538
|
-
def tag_end(name)
|
539
|
-
if name =~ /\Ah\d+/
|
540
|
-
@headlines.push({ 'level' => @level, 'id' => @id, 'title' => @content, 'notoc' => @notoc }) if @id.present?
|
541
|
-
@content = ''
|
542
|
-
@level = nil
|
543
|
-
@id = nil
|
544
|
-
@notoc = nil
|
545
|
-
end
|
546
|
-
|
547
|
-
true
|
548
|
-
end
|
549
|
-
|
550
|
-
def text(text)
|
551
|
-
@content << text.gsub("\t", ' ') if @level.present?
|
552
|
-
end
|
553
|
-
end
|
554
598
|
end
|
555
599
|
end
|