review 2.4.0 → 2.5.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.
Files changed (54) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +20 -5
  3. data/.travis.yml +2 -1
  4. data/NEWS.ja.md +93 -0
  5. data/NEWS.md +77 -0
  6. data/README.md +1 -1
  7. data/bin/review +38 -12
  8. data/bin/review-compile +106 -88
  9. data/bin/review-epubmaker +6 -1
  10. data/bin/review-init +21 -1
  11. data/bin/review-textmaker +16 -0
  12. data/doc/config.yml.sample +6 -1
  13. data/doc/format.ja.md +23 -0
  14. data/doc/format.md +20 -2
  15. data/doc/quickstart.ja.md +8 -4
  16. data/doc/quickstart.md +11 -8
  17. data/lib/review/book/base.rb +29 -18
  18. data/lib/review/book/index.rb +10 -5
  19. data/lib/review/builder.rb +58 -33
  20. data/lib/review/catalog.rb +30 -0
  21. data/lib/review/compiler.rb +53 -19
  22. data/lib/review/configure.rb +15 -14
  23. data/lib/review/epubmaker.rb +15 -4
  24. data/lib/review/htmlbuilder.rb +56 -24
  25. data/lib/review/idgxmlbuilder.rb +17 -7
  26. data/lib/review/latexbuilder.rb +113 -38
  27. data/lib/review/markdownbuilder.rb +12 -5
  28. data/lib/review/md2inaobuilder.rb +3 -1
  29. data/lib/review/pdfmaker.rb +23 -9
  30. data/lib/review/plaintextbuilder.rb +683 -0
  31. data/lib/review/rstbuilder.rb +30 -10
  32. data/lib/review/textmaker.rb +158 -0
  33. data/lib/review/textutils.rb +10 -1
  34. data/lib/review/topbuilder.rb +32 -417
  35. data/lib/review/version.rb +1 -1
  36. data/lib/review/webmaker.rb +29 -8
  37. data/review.gemspec +3 -4
  38. data/templates/html/layout-xhtml1.html.erb +0 -2
  39. data/templates/latex/layout.tex.erb +6 -4
  40. data/templates/web/html/layout-xhtml1.html.erb +0 -2
  41. data/test/book_test_helper.rb +1 -0
  42. data/test/run_test.rb +1 -1
  43. data/test/sample-book/src/Rakefile +19 -3
  44. data/test/syntax-book/Rakefile +19 -3
  45. data/test/test_catalog.rb +45 -0
  46. data/test/test_compiler.rb +8 -2
  47. data/test/test_htmlbuilder.rb +22 -0
  48. data/test/test_idgxmlbuilder.rb +22 -0
  49. data/test/test_index.rb +31 -0
  50. data/test/test_latexbuilder.rb +48 -16
  51. data/test/test_plaintextbuilder.rb +390 -0
  52. data/test/test_textutils.rb +2 -0
  53. data/test/test_topbuilder.rb +23 -1
  54. metadata +13 -7
@@ -1,3 +1,3 @@
1
1
  module ReVIEW
2
- VERSION = '2.4.0'.freeze
2
+ VERSION = '2.5.0'.freeze
3
3
  end
@@ -13,6 +13,7 @@ require 'review/converter'
13
13
  require 'review/configure'
14
14
  require 'review/book'
15
15
  require 'review/htmlbuilder'
16
+ require 'review/yamlloader'
16
17
  require 'review/template'
17
18
  require 'review/tocprinter'
18
19
  require 'review/version'
@@ -29,6 +30,15 @@ module ReVIEW
29
30
  @logger = ReVIEW.logger
30
31
  end
31
32
 
33
+ def error(msg)
34
+ @logger.error "#{File.basename($PROGRAM_NAME, '.*')}: #{msg}"
35
+ exit 1
36
+ end
37
+
38
+ def warn(msg)
39
+ @logger.warn "#{File.basename($PROGRAM_NAME, '.*')}: #{msg}"
40
+ end
41
+
32
42
  def self.execute(*args)
33
43
  self.new.execute(*args)
34
44
  end
@@ -68,13 +78,24 @@ module ReVIEW
68
78
  @config = ReVIEW::Configure.values
69
79
  @config.maker = 'webmaker'
70
80
  cmd_config, yamlfile = parse_opts(args)
81
+ error "#{yamlfile} not found." unless File.exist?(yamlfile)
71
82
 
72
- @config.merge!(YAML.load_file(yamlfile))
83
+ begin
84
+ loader = ReVIEW::YAMLLoader.new
85
+ @config.deep_merge!(loader.load_file(yamlfile))
86
+ rescue => e
87
+ error "yaml error #{e.message}"
88
+ end
73
89
  # YAML configs will be overridden by command line options.
74
- @config.merge!(cmd_config)
90
+ @config.deep_merge!(cmd_config)
75
91
  @config['htmlext'] = 'html'
76
92
  I18n.setup(@config['language'])
77
- generate_html_files(yamlfile)
93
+ begin
94
+ generate_html_files(yamlfile)
95
+ rescue ApplicationError => e
96
+ raise if @config['debug']
97
+ error(e.message)
98
+ end
78
99
  end
79
100
 
80
101
  def generate_html_files(yamlfile)
@@ -154,14 +175,14 @@ module ReVIEW
154
175
  htmlfile = "#{id}.#{@config['htmlext']}"
155
176
 
156
177
  if @config['params'].present?
157
- @logger.warn %Q('params:' in config.yml is obsoleted.)
178
+ warn %Q('params:' in config.yml is obsoleted.)
158
179
  end
159
180
 
160
181
  begin
161
182
  @converter.convert(filename, File.join(basetmpdir, htmlfile))
162
183
  rescue => e
163
- @logger.warn "compile error in #{filename} (#{e.class})"
164
- @logger.warn e.message
184
+ warn "compile error in #{filename} (#{e.class})"
185
+ warn e.message
165
186
  end
166
187
  end
167
188
 
@@ -240,7 +261,7 @@ module ReVIEW
240
261
  @body << %Q(<div class="titlepage">)
241
262
  @body << %Q(<h1 class="tp-title">#{CGI.escapeHTML(@config.name_of('booktitle'))}</h1>)
242
263
  @body << %Q(<h2 class="tp-author">#{join_with_separator(@config.names_of('aut'), ReVIEW::I18n.t('names_splitter'))}</h2>) if @config['aut']
243
- @body << %Q(<h3 class="tp-publisher">#{join_with_separator(@config.names_of('prt'), ReVIEW::I18n.t('names_splitter'))}</h3>) if @config['prt']
264
+ @body << %Q(<h3 class="tp-publisher">#{join_with_separator(@config.names_of('pbl'), ReVIEW::I18n.t('names_splitter'))}</h3>) if @config['pbl']
244
265
  @body << '</div>'
245
266
 
246
267
  @language = @config['language']
@@ -262,7 +283,7 @@ module ReVIEW
262
283
  def copy_file_with_param(name, target_file = nil)
263
284
  return if @config[name].nil? || !File.exist?(@config[name])
264
285
  target_file ||= File.basename(@config[name])
265
- FileUtils.cp(@config[name], File.join(basetmpdir, target_file))
286
+ FileUtils.cp(@config[name], File.join(@path, target_file))
266
287
  end
267
288
 
268
289
  def join_with_separator(value, sep)
@@ -12,13 +12,12 @@ Gem::Specification.new do |gem|
12
12
  gem.summary = 'Re:VIEW: a easy-to-use digital publishing system'
13
13
  gem.description = 'Re:VIEW is a digital publishing system for books and ebooks. It supports InDesign, EPUB and LaTeX.'
14
14
  gem.required_rubygems_version = Gem::Requirement.new('>= 0') if gem.respond_to? :required_rubygems_version=
15
- gem.date = '2017-06-29'
15
+ gem.date = '2018-03-01'
16
16
 
17
17
  gem.files = `git ls-files`.split("\n")
18
18
  gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
19
  gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
20
- gem.extra_rdoc_files = [
21
- ]
20
+ gem.extra_rdoc_files = []
22
21
  gem.require_paths = ['lib']
23
22
 
24
23
  gem.add_dependency('image_size')
@@ -26,6 +25,6 @@ Gem::Specification.new do |gem|
26
25
  gem.add_dependency('rubyzip')
27
26
  gem.add_development_dependency('pygments.rb')
28
27
  gem.add_development_dependency('rake')
29
- gem.add_development_dependency('rubocop')
28
+ gem.add_development_dependency('rubocop', '~> 0.52.0')
30
29
  gem.add_development_dependency('test-unit')
31
30
  end
@@ -13,8 +13,6 @@
13
13
  <title><%= @title %></title>
14
14
  </head>
15
15
  <body<%= @body_ext %>>
16
- <% if @error_messages %><%= @error_messages %><% end %>
17
- <% if @warning_messages %><%= @warning_messages %><% end %>
18
16
  <%= @body %>
19
17
  </body>
20
18
  </html>
@@ -249,8 +249,10 @@
249
249
  }
250
250
  \makeatother
251
251
 
252
- <%- if @config["usepackage"] -%>
253
- <%= @config["usepackage"] %>
252
+ <%- if @config["texstyle"] -%>
253
+ <%- [@config["texstyle"]].flatten.each do |x| -%>
254
+ \usepackage{<%= x %>}
255
+ <%- end -%>
254
256
  <%- end -%>
255
257
  <%- if @config["makeindex"] -%>
256
258
  \usepackage{makeidx}
@@ -360,7 +362,7 @@
360
362
  <%- if @config["subtitle"] -%>
361
363
  {\noindent\reviewtitlefont\large <%= escape_latex(@config.name_of("subtitle")) %>} \\
362
364
  <%- end -%>
363
- \rule[8pt]{14cm}{1pt} \\
365
+ \rule[8pt]{\textwidth}{1pt} \\
364
366
  {\noindent
365
367
  <%= @config["pubhistory"].to_s.gsub(/\n/){"\n\n\\noindent\n"} %>
366
368
  }
@@ -369,7 +371,7 @@
369
371
  <%= @okuduke %>
370
372
  \end{tabular}
371
373
   \\
372
- \rule[0pt]{14cm}{1pt} \\
374
+ \rule[0pt]{\textwidth}{1pt} \\
373
375
  <%- if @config["rights"] -%>
374
376
  <%= @config.names_of("rights").map{|s| escape_latex(s)}.join('\\' + '\\') %> \\
375
377
  <%- end -%>
@@ -13,8 +13,6 @@
13
13
  <title><%= @title %></title>
14
14
  </head>
15
15
  <body<%= @body_ext %>>
16
- <% if @error_messages %><%= @error_messages %><% end %>
17
- <% if @warning_messages %><%= @warning_messages %><% end %>
18
16
  <%= @body %>
19
17
  </body>
20
18
  </html>
@@ -1,4 +1,5 @@
1
1
  require 'test_helper'
2
+ require 'book_test_helper'
2
3
  require 'review/book'
3
4
 
4
5
  require 'stringio'
@@ -6,5 +6,5 @@ $LOAD_PATH.unshift(lib_dir)
6
6
 
7
7
  require 'test/unit'
8
8
 
9
- argv = ['--max-diff-target-string-size=10000']
9
+ argv = ARGV || ['--max-diff-target-string-size=10000']
10
10
  exit Test::Unit::AutoRunner.run(true, test_dir, argv)
@@ -6,10 +6,12 @@ BOOK_PDF = BOOK + '.pdf'
6
6
  BOOK_EPUB = BOOK + '.epub'
7
7
  CONFIG_FILE = 'config.yml'
8
8
  WEBROOT = 'webroot'
9
+ TEXTROOT = BOOK + '-text'
10
+ TOPROOT = BOOK + '-text'
9
11
 
10
12
  def build(mode, chapter)
11
13
  sh "review-compile --target=#{mode} --footnotetext --stylesheet=style.css #{chapter} > tmp"
12
- mode_ext = { 'html' => 'html', 'latex' => 'tex', 'idgxml' => 'xml' }
14
+ mode_ext = { 'html' => 'html', 'latex' => 'tex', 'idgxml' => 'xml', 'top' => 'txt', 'plaintext' => 'txt' }
13
15
  FileUtils.mv 'tmp', chapter.gsub(/re\z/, mode_ext[mode])
14
16
  end
15
17
 
@@ -46,9 +48,19 @@ task all: %i[pdf epub]
46
48
  desc 'generate PDF file'
47
49
  task pdf: BOOK_PDF
48
50
 
49
- desc 'generate stagic HTML file for web'
51
+ desc 'generate static HTML file for web'
50
52
  task web: WEBROOT
51
53
 
54
+ desc 'generate text file (without decoration)'
55
+ task plaintext: TEXTROOT do
56
+ sh "review-textmaker -n #{CONFIG_FILE}"
57
+ end
58
+
59
+ desc 'generate (decorated) text file'
60
+ task text: TOPROOT do
61
+ sh "review-textmaker #{CONFIG_FILE}"
62
+ end
63
+
52
64
  desc 'generate EPUB file'
53
65
  task epub: BOOK_EPUB
54
66
 
@@ -69,4 +81,8 @@ file WEBROOT => SRC do
69
81
  sh "review-webmaker #{CONFIG_FILE}"
70
82
  end
71
83
 
72
- CLEAN.include([BOOK, BOOK_PDF, BOOK_EPUB, BOOK + '-pdf', BOOK + '-epub', WEBROOT, 'images/_review_math'])
84
+ file TEXTROOT => SRC do
85
+ FileUtils.rm_rf [TEXTROOT]
86
+ end
87
+
88
+ CLEAN.include([BOOK, BOOK_PDF, BOOK_EPUB, BOOK + '-pdf', BOOK + '-epub', WEBROOT, 'images/_review_math', TEXTROOT])
@@ -6,10 +6,12 @@ BOOK_PDF = BOOK + '.pdf'
6
6
  BOOK_EPUB = BOOK + '.epub'
7
7
  CONFIG_FILE = 'config.yml'
8
8
  WEBROOT = 'webroot'
9
+ TEXTROOT = BOOK + '-text'
10
+ TOPROOT = BOOK + '-text'
9
11
 
10
12
  def build(mode, chapter)
11
13
  sh "review-compile --target=#{mode} --footnotetext --stylesheet=style.css #{chapter} > tmp"
12
- mode_ext = { 'html' => 'html', 'latex' => 'tex', 'idgxml' => 'xml' }
14
+ mode_ext = { 'html' => 'html', 'latex' => 'tex', 'idgxml' => 'xml', 'top' => 'txt', 'plaintext' => 'txt' }
13
15
  FileUtils.mv 'tmp', chapter.gsub(/re\z/, mode_ext[mode])
14
16
  end
15
17
 
@@ -46,9 +48,19 @@ task all: %i[pdf epub]
46
48
  desc 'generate PDF file'
47
49
  task pdf: BOOK_PDF
48
50
 
49
- desc 'generate stagic HTML file for web'
51
+ desc 'generate static HTML file for web'
50
52
  task web: WEBROOT
51
53
 
54
+ desc 'generate plaintext file'
55
+ task plaintext: TEXTROOT do
56
+ sh "review-textmaker -n #{CONFIG_FILE}"
57
+ end
58
+
59
+ desc 'generate decorated text file'
60
+ task text: TOPROOT do
61
+ sh "review-textmaker #{CONFIG_FILE}"
62
+ end
63
+
52
64
  desc 'generate EPUB file'
53
65
  task epub: BOOK_EPUB
54
66
 
@@ -69,4 +81,8 @@ file WEBROOT => SRC do
69
81
  sh "review-webmaker #{CONFIG_FILE}"
70
82
  end
71
83
 
72
- CLEAN.include([BOOK, BOOK_PDF, BOOK_EPUB, BOOK + '-pdf', BOOK + '-epub', WEBROOT])
84
+ file TEXTROOT => SRC do
85
+ FileUtils.rm_rf [TEXTROOT]
86
+ end
87
+
88
+ CLEAN.include([BOOK, BOOK_PDF, BOOK_EPUB, BOOK + '-pdf', BOOK + '-epub', WEBROOT, 'images/_review_math', TEXTROOT])
@@ -3,6 +3,7 @@ require 'review/catalog'
3
3
 
4
4
  class CatalogTest < Test::Unit::TestCase
5
5
  include ReVIEW
6
+ include BookTestHelper
6
7
 
7
8
  def test_predef
8
9
  sut = Catalog.new(yaml)
@@ -90,6 +91,50 @@ ch02.re
90
91
  assert_equal(exp.chomp, sut.chaps)
91
92
  end
92
93
 
94
+ def test_validate
95
+ mktmpbookdir do |dir, _book, _files|
96
+ %w[pre01.re pre02.re ch01.re ch02.re post01.re post02.re back01.re back02.re].each do |file|
97
+ FileUtils.touch(file)
98
+ end
99
+ cat = Catalog.new(yaml_hash)
100
+ cat.validate!(dir)
101
+ end
102
+ end
103
+
104
+ def test_validate_with_parts
105
+ mktmpbookdir do |dir, _book, _files|
106
+ %w[ch01.re part1.re ch02.re ch03.re part2.re ch04.re ch05.re].each do |file|
107
+ FileUtils.touch(file)
108
+ end
109
+ cat = Catalog.new(yaml_with_parts)
110
+ cat.validate!(dir)
111
+ end
112
+ end
113
+
114
+ def test_validate_fail_ch02
115
+ assert_raise FileNotFound do
116
+ mktmpbookdir do |dir, _book, _files|
117
+ %w[pre01.re pre02.re ch01.re].each do |file|
118
+ FileUtils.touch(file)
119
+ end
120
+ cat = Catalog.new(yaml_hash)
121
+ cat.validate!(dir)
122
+ end
123
+ end
124
+ end
125
+
126
+ def test_validate_fail_back02
127
+ assert_raise FileNotFound do
128
+ mktmpbookdir do |dir, _book, _files|
129
+ %w[pre01.re pre02.re ch01.re ch02.re post01.re post02.re back01.re back03.re].each do |file|
130
+ FileUtils.touch(file)
131
+ end
132
+ cat = Catalog.new(yaml_hash)
133
+ cat.validate!(dir)
134
+ end
135
+ end
136
+ end
137
+
93
138
  private
94
139
 
95
140
  def yaml
@@ -42,7 +42,13 @@ class CompilerTest < Test::Unit::TestCase
42
42
  end
43
43
 
44
44
  def test_replace_fence
45
- actual = @c.__send__(:replace_fence, '@<m>${}\\}|$, @<m>|{}\\}\\$|, @<m>|\\{\\a\\}|, @<tt>|}|, @<tt>|\\|, @<tt>|\\\\|, @<tt>|\\\\\\|')
46
- assert_equal '@<m>{{\\}\\\\\\}|}, @<m>{{\\}\\\\\\}\\$}, @<m>{\\{\\a\\\\\\}}, @<tt>{\\}}, @<tt>{\\\\}, @<tt>{\\\\\\\\}, @<tt>{\\\\\\\\\\\\}', actual
45
+ source_str = <<-'EOB'
46
+ @<m>${}\}|$, @<m>|{}\}\$|, @<m>|\{\a\}|, @<tt>|}|, @<tt>|\|, @<tt>|\\|, @<tt>|\\\|
47
+ EOB
48
+ expected = <<-'EOB'
49
+ @<m>{{\}\\\}|}, @<m>{{\}\\\}\$}, @<m>{\{\a\\\}}, @<tt>{\}}, @<tt>{\\}, @<tt>{\\\\}, @<tt>{\\\\\\}
50
+ EOB
51
+ actual = @c.__send__(:replace_fence, source_str)
52
+ assert_equal expected, actual
47
53
  end
48
54
  end
@@ -430,6 +430,11 @@ EOS
430
430
  assert_equal %Q(<div class="memo">\n<p class="caption">this is <b>test</b>&lt;&amp;&gt;_</p>\n<p>test1</p>\n<p>test<i>2</i></p>\n</div>\n), actual
431
431
  end
432
432
 
433
+ def test_blankline
434
+ actual = compile_block("//blankline\nfoo\n")
435
+ assert_equal %Q(<p><br /></p>\n<p>foo</p>\n), actual
436
+ end
437
+
433
438
  def test_noindent
434
439
  @builder.noindent
435
440
  actual = compile_block("foo\nbar\n\nfoo2\nbar2\n")
@@ -1686,4 +1691,21 @@ EOS
1686
1691
  actual = compile_inline('test @<code>|@<code>{$サンプル$}|')
1687
1692
  assert_equal 'test <code class="inline-code tt">@&lt;code&gt;{$サンプル$}</code>', actual
1688
1693
  end
1694
+
1695
+ def test_inline_unknown
1696
+ e = assert_raises(ReVIEW::ApplicationError) { compile_block "@<img>{n}\n" }
1697
+ assert_equal ':1: error: unknown image: n', e.message
1698
+ e = assert_raises(ReVIEW::ApplicationError) { compile_block "@<fn>{n}\n" }
1699
+ assert_equal ':1: error: unknown footnote: n', e.message
1700
+ e = assert_raises(ReVIEW::ApplicationError) { compile_block "@<hd>{n}\n" }
1701
+ assert_equal ':1: error: unknown headline: n', e.message
1702
+ %w[list table column].each do |name|
1703
+ e = assert_raises(ReVIEW::ApplicationError) { compile_block "@<#{name}>{n}\n" }
1704
+ assert_equal ":1: error: unknown #{name}: n", e.message
1705
+ end
1706
+ %w[chap chapref title].each do |name|
1707
+ e = assert_raises(ReVIEW::ApplicationError) { compile_block "@<#{name}>{n}\n" }
1708
+ assert_equal ':1: error: key not found: "n"', e.message
1709
+ end
1710
+ end
1689
1711
  end
@@ -341,6 +341,11 @@ class IDGXMLBuidlerTest < Test::Unit::TestCase
341
341
  assert_equal %Q(<p align='center'>foobar</p><p align='center'>buz</p>), actual
342
342
  end
343
343
 
344
+ def test_blankline
345
+ actual = compile_block("//blankline\nfoo\n")
346
+ assert_equal %Q(<p/><p>foo</p>), actual
347
+ end
348
+
344
349
  def test_noindent
345
350
  actual = compile_block("//noindent\nfoo\nbar\n\nfoo2\nbar2\n")
346
351
  assert_equal %Q(<p aid:pstyle="noindent" noindent='1'>foobar</p><p>foo2bar2</p>), actual
@@ -614,6 +619,23 @@ EOS
614
619
  assert_equal expected, actual
615
620
  end
616
621
 
622
+ def test_inline_unknown
623
+ e = assert_raises(ReVIEW::ApplicationError) { compile_block "@<img>{n}\n" }
624
+ assert_equal ':1: error: unknown image: n', e.message
625
+ e = assert_raises(ReVIEW::ApplicationError) { compile_block "@<fn>{n}\n" }
626
+ assert_equal ':1: error: unknown footnote: n', e.message
627
+ e = assert_raises(ReVIEW::ApplicationError) { compile_block "@<hd>{n}\n" }
628
+ assert_equal ':1: error: unknown headline: n', e.message
629
+ %w[list table column].each do |name|
630
+ e = assert_raises(ReVIEW::ApplicationError) { compile_block "@<#{name}>{n}\n" }
631
+ assert_equal ":1: error: unknown #{name}: n", e.message
632
+ end
633
+ %w[chap chapref title].each do |name|
634
+ e = assert_raises(ReVIEW::ApplicationError) { compile_block "@<#{name}>{n}\n" }
635
+ assert_equal ':1: error: key not found: "n"', e.message
636
+ end
637
+ end
638
+
617
639
  def test_inline_raw0
618
640
  assert_equal 'normal', compile_inline('@<raw>{normal}')
619
641
  end
@@ -177,4 +177,35 @@ class IndexTest < Test::Unit::TestCase
177
177
  index = Book::HeadlineIndex.parse(src, chap)
178
178
  assert_equal '1.1.1', index.number('sec1-1')
179
179
  end
180
+
181
+ def test_headeline_index9
182
+ src = <<-EOB
183
+ = chap1
184
+ == sec1
185
+ === sec1-1
186
+ ===[column] column1
187
+ ===[/column]
188
+ ==== sec1-1-1
189
+ === sec1-2
190
+ EOB
191
+ book = Book::Base.load
192
+ chap = Book::Chapter.new(book, 1, '-', nil)
193
+ index = Book::HeadlineIndex.parse(src, chap)
194
+ assert_equal [1, 1, 1], index['sec1-1-1'].number
195
+ end
196
+
197
+ def test_headeline_index10
198
+ src = <<-EOB
199
+ = chap1
200
+ == sec1
201
+ === sec1-1
202
+ ====[column] column1
203
+ ==== sec1-1-1
204
+ === sec1-2
205
+ EOB
206
+ book = Book::Base.load
207
+ chap = Book::Chapter.new(book, 1, '-', nil)
208
+ index = Book::HeadlineIndex.parse(src, chap)
209
+ assert_equal [1, 1, 1], index['sec1-1-1'].number
210
+ end
180
211
  end