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.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +28 -10
  3. data/.travis.yml +11 -2
  4. data/NEWS.ja.md +89 -17
  5. data/NEWS.md +92 -0
  6. data/README.md +1 -1
  7. data/Rakefile +0 -13
  8. data/bin/review-catalog-converter +83 -37
  9. data/bin/review-check +17 -5
  10. data/bin/review-compile +1 -1
  11. data/bin/review-index +6 -0
  12. data/bin/review-init +3 -155
  13. data/bin/review-preproc +0 -5
  14. data/bin/review-validate +21 -7
  15. data/bin/review-vol +13 -5
  16. data/doc/config.yml.sample +12 -7
  17. data/doc/config.yml.sample-simple +1 -1
  18. data/doc/format.ja.md +39 -3
  19. data/doc/format.md +39 -3
  20. data/doc/format_idg.ja.md +0 -4
  21. data/doc/pdfmaker.ja.md +1 -1
  22. data/doc/pdfmaker.md +1 -1
  23. data/doc/sample.css +7 -0
  24. data/lib/epubmaker/content.rb +31 -12
  25. data/lib/epubmaker/epubcommon.rb +10 -3
  26. data/lib/epubmaker/epubv2.rb +11 -3
  27. data/lib/epubmaker/epubv3.rb +11 -3
  28. data/lib/epubmaker/producer.rb +55 -20
  29. data/lib/review/book/base.rb +63 -48
  30. data/lib/review/book/chapter.rb +19 -7
  31. data/lib/review/book/compilable.rb +5 -20
  32. data/lib/review/book/image_finder.rb +10 -3
  33. data/lib/review/book/index.rb +30 -9
  34. data/lib/review/book/part.rb +9 -6
  35. data/lib/review/book.rb +0 -14
  36. data/lib/review/builder.rb +110 -18
  37. data/lib/review/catalog.rb +24 -4
  38. data/lib/review/compiler.rb +3 -1
  39. data/lib/review/configure.rb +43 -9
  40. data/lib/review/epubmaker/reviewheaderlistener.rb +57 -0
  41. data/lib/review/epubmaker.rb +129 -85
  42. data/lib/review/htmlbuilder.rb +76 -58
  43. data/lib/review/htmlutils.rb +20 -13
  44. data/lib/review/i18n.rb +6 -2
  45. data/lib/review/idgxmlbuilder.rb +52 -41
  46. data/lib/review/init.rb +194 -0
  47. data/lib/review/latexbuilder.rb +118 -34
  48. data/lib/review/latexutils.rb +5 -5
  49. data/lib/review/logger.rb +2 -1
  50. data/lib/review/makerhelper.rb +1 -1
  51. data/lib/review/markdownbuilder.rb +66 -6
  52. data/lib/review/md2inaobuilder.rb +2 -2
  53. data/lib/review/pdfmaker.rb +74 -22
  54. data/lib/review/plaintextbuilder.rb +8 -4
  55. data/lib/review/preprocessor.rb +14 -17
  56. data/lib/review/sec_counter.rb +8 -2
  57. data/lib/review/textmaker.rb +2 -2
  58. data/lib/review/textutils.rb +9 -2
  59. data/lib/review/tocparser.rb +7 -4
  60. data/lib/review/tocprinter.rb +3 -1
  61. data/lib/review/version.rb +1 -1
  62. data/lib/review/webmaker.rb +19 -7
  63. data/lib/review/webtocprinter.rb +8 -4
  64. data/review.gemspec +4 -3
  65. data/templates/latex/config.erb +84 -0
  66. data/templates/latex/layout.tex.erb +76 -361
  67. data/templates/latex/review-jlreq/README.md +22 -0
  68. data/templates/latex/review-jlreq/review-base.sty +178 -0
  69. data/templates/latex/review-jlreq/review-custom.sty +1 -0
  70. data/templates/latex/review-jlreq/review-jlreq.cls +141 -0
  71. data/templates/latex/review-jlreq/review-style.sty +149 -0
  72. data/templates/latex/review-jlreq/reviewmacro.sty +8 -0
  73. data/templates/latex/review-jsbook/jumoline.sty +310 -0
  74. data/templates/latex/review-jsbook/plistings.sty +326 -0
  75. data/templates/latex/review-jsbook/review-base.sty +405 -0
  76. data/templates/latex/review-jsbook/review-custom.sty +1 -0
  77. data/templates/latex/review-jsbook/review-style.sty +38 -0
  78. data/templates/latex/review-jsbook/reviewmacro.sty +8 -0
  79. data/templates/latex-compat2/layout.tex.erb +387 -0
  80. data/test/assets/test_template.tex +105 -235
  81. data/test/assets/test_template_backmatter.tex +133 -14
  82. data/test/book_test_helper.rb +1 -1
  83. data/test/run_test.rb +2 -0
  84. data/test/sample-book/src/Rakefile +11 -6
  85. data/test/sample-book/src/config.yml +2 -2
  86. data/test/sample-book/src/sty/reviewmacro.sty +1 -39
  87. data/test/sample-book/src/style.css +6 -0
  88. data/test/syntax-book/config.yml +1 -1
  89. data/test/test_book.rb +13 -16
  90. data/test/test_book_chapter.rb +4 -10
  91. data/test/test_book_part.rb +4 -3
  92. data/test/test_catalog.rb +15 -4
  93. data/test/test_helper.rb +2 -2
  94. data/test/test_htmlbuilder.rb +78 -10
  95. data/test/test_htmlutils.rb +12 -5
  96. data/test/test_idgxmlbuilder.rb +1 -1
  97. data/test/test_latexbuilder.rb +94 -49
  98. data/test/test_latexbuilder_v2.rb +1077 -0
  99. data/test/test_logger.rb +20 -0
  100. data/test/test_markdownbuilder.rb +10 -0
  101. data/test/test_pdfmaker.rb +6 -7
  102. data/test/test_plaintextbuilder.rb +1 -1
  103. data/test/test_review_ext.rb +0 -1
  104. data/test/test_rstbuilder.rb +1 -1
  105. data/test/test_topbuilder.rb +19 -7
  106. data/test/test_webtocprinter.rb +14 -14
  107. data/{test/sample-book/src/vendor → vendor}/jumoline/README +0 -0
  108. data/{test/sample-book/src/vendor → vendor}/jumoline/jumoline.dtx +0 -0
  109. data/{test/sample-book/src/vendor → vendor}/jumoline/jumoline.ins +0 -0
  110. data/{test/sample-book/src/vendor → vendor}/jumoline/lppl.txt +0 -0
  111. data/vendor/plistings/.gitignore +9 -0
  112. data/vendor/plistings/LICENSE +21 -0
  113. data/vendor/plistings/README.md +18 -0
  114. data/vendor/plistings/plistings.sty +326 -0
  115. data/vendor/plistings/test1.tex +174 -0
  116. data/vendor/plistings/test2.tex +54 -0
  117. metadata +48 -19
  118. data/lib/review/unfold.rb +0 -129
  119. data/test/CHAPS +0 -2
  120. data/test/bib.re +0 -13
  121. data/test/test.re +0 -43
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2017 Kenshi Muto and Masayoshi Takahashi
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
- puts s if @config['debug'].present?
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
- FileUtils.rm_rf(path, secure: true) if File.exist?(path)
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 = @config['bookname'] if bookname.nil?
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
- FileUtils.rm_rf(booktmpname) if @config['debug']
96
+ if @config['debug']
97
+ FileUtils.rm_rf(booktmpname)
98
+ end
92
99
  math_dir = "./#{@config['imagedir']}/_review_math"
93
- FileUtils.rm_rf(math_dir) if @config['imgmath'] && Dir.exist?(math_dir)
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
- if content.media == 'application/xhtml+xml'
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
- content.properties.push('svg') if e.attributes['src'] =~ /svg\Z/i
179
+ if e.attributes['src'] =~ /svg\Z/i
180
+ content.properties.push('svg')
181
+ end
170
182
  end
171
183
  end
172
- elsif content.media == 'text/css'
184
+ when 'text/css'
173
185
  File.open("#{basetmpdir}/#{content.file}") do |f|
174
186
  f.each_line do |l|
175
- l.scan(/url\((.+?)\)/) { |_m| @config['epubmaker']['force_include_images'].push($1.strip) }
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 = @config['image_ext'] if allow_exts.nil?
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
- warn "#{file} is not found, skip." if file !~ /\Ahttp[s]?:/
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 = @config['image_ext'] if allow_exts.nil?
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
- title += ReVIEW::I18n.t('chapter_postfix') + part.name.strip if part.name.strip.present?
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
- prop_str = ''
380
- prop_str = ',properties=' + properties.join(' ') if properties.present?
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
- headline['level'] = 0 if ispart.present? && headline['level'] == 1
404
+ if ispart.present? && headline['level'] == 1
405
+ headline['level'] = 0
406
+ end
384
407
  if first.nil?
385
- @htmltoc.add_item(headline['level'], filename + '#' + headline['id'], headline['title'], { chaptype: chaptype, notoc: headline['notoc'] })
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'], filename, headline['title'], { force_include: true, chaptype: chaptype + prop_str, notoc: headline['notoc'] })
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, 'level' => level.to_i, 'title' => title, 'chaptype' => args[:chaptype] }
400
- hash['id'] = args[:id] if args[:id].present?
401
- hash['properties'] = args[:properties].split(' ') if args[:properties].present?
402
- hash['notoc'] = args[:notoc] if args[:notoc].present?
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
- FileUtils.cp(@config['cover'], "#{basetmpdir}/#{File.basename(@config['cover'])}") if @config['cover'].present? && File.exist?(@config['cover'])
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'], "#{basetmpdir}/titlepage.#{@config['htmlext']}")
466
+ FileUtils.cp(@config['titlefile'],
467
+ "#{basetmpdir}/titlepage.#{@config['htmlext']}")
423
468
  end
424
- @htmltoc.add_item(1, "titlepage.#{@config['htmlext']}", @producer.res.v('titlepagetitle'), chaptype: 'pre')
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'], "#{basetmpdir}/#{File.basename(@config['originaltitlefile'])}")
429
- @htmltoc.add_item(1, File.basename(@config['originaltitlefile']), @producer.res.v('originaltitle'), chaptype: 'pre')
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'], "#{basetmpdir}/#{File.basename(@config['creditfile'])}")
434
- @htmltoc.add_item(1, File.basename(@config['creditfile']), @producer.res.v('credittitle'), chaptype: 'pre')
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
- @body << %Q(<h2 class="tp-subtitle">#{CGI.escapeHTML(@config.name_of('subtitle'))}</h2>\n) if @config['subtitle']
448
- @body << %Q(<h2 class="tp-author">#{CGI.escapeHTML(@config.names_of('aut').join(ReVIEW::I18n.t('names_splitter')))}</h2>\n) if @config['aut']
449
- @body << %Q(<h3 class="tp-publisher">#{CGI.escapeHTML(@config.names_of('pbl').join(ReVIEW::I18n.t('names_splitter')))}</h3>\n) if @config['pbl']
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'], "#{basetmpdir}/#{File.basename(@config['profile'])}")
463
- @htmltoc.add_item(1, File.basename(@config['profile']), @producer.res.v('profiletitle'), chaptype: 'post')
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'], "#{basetmpdir}/#{File.basename(@config['advfile'])}")
468
- @htmltoc.add_item(1, File.basename(@config['advfile']), @producer.res.v('advtitle'), chaptype: 'post')
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'], "#{basetmpdir}/colophon.#{@config['htmlext']}")
543
+ FileUtils.cp(@config['colophon'],
544
+ "#{basetmpdir}/colophon.#{@config['htmlext']}")
474
545
  else
475
- File.open("#{basetmpdir}/colophon.#{@config['htmlext']}", 'w') { |f| @producer.colophon(f) }
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, "colophon.#{@config['htmlext']}", @producer.res.v('colophontitle'), chaptype: 'post')
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'], "#{basetmpdir}/#{File.basename(@config['backcover'])}")
482
- @htmltoc.add_item(1, File.basename(@config['backcover']), @producer.res.v('backcovertitle'), chaptype: 'post')
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') { |f| f.puts "#{htmlfile},#{reviewfile}" }
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
- extre = Regexp.new('\\.(' + allow_exts.delete_if { |t| %w[ttf woff otf].include?(t) }.join('|') + ')', Regexp::IGNORECASE)
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