asciidoctor 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +10 -0
  3. data/Guardfile +18 -0
  4. data/LICENSE +1 -1
  5. data/README.adoc +65 -21
  6. data/Rakefile +10 -0
  7. data/asciidoctor.gemspec +17 -35
  8. data/compat/asciidoc.conf +130 -13
  9. data/lib/asciidoctor.rb +107 -87
  10. data/lib/asciidoctor/abstract_block.rb +6 -2
  11. data/lib/asciidoctor/abstract_node.rb +21 -13
  12. data/lib/asciidoctor/attribute_list.rb +2 -5
  13. data/{stylesheets/asciidoctor.css → lib/asciidoctor/backends/_stylesheets.rb} +96 -46
  14. data/lib/asciidoctor/backends/base_template.rb +9 -4
  15. data/lib/asciidoctor/backends/docbook45.rb +246 -138
  16. data/lib/asciidoctor/backends/html5.rb +580 -381
  17. data/lib/asciidoctor/block.rb +2 -50
  18. data/lib/asciidoctor/cli/options.rb +9 -8
  19. data/lib/asciidoctor/document.rb +35 -45
  20. data/lib/asciidoctor/helpers.rb +10 -0
  21. data/lib/asciidoctor/lexer.rb +456 -148
  22. data/lib/asciidoctor/list_item.rb +0 -21
  23. data/lib/asciidoctor/path_resolver.rb +18 -12
  24. data/lib/asciidoctor/reader.rb +71 -26
  25. data/lib/asciidoctor/renderer.rb +2 -19
  26. data/lib/asciidoctor/section.rb +0 -1
  27. data/lib/asciidoctor/substituters.rb +150 -36
  28. data/lib/asciidoctor/table.rb +30 -24
  29. data/lib/asciidoctor/version.rb +1 -1
  30. data/man/asciidoctor.1 +22 -16
  31. data/man/asciidoctor.ad +24 -16
  32. data/test/attributes_test.rb +50 -0
  33. data/test/blocks_test.rb +660 -9
  34. data/test/document_test.rb +191 -14
  35. data/test/fixtures/encoding.asciidoc +8 -0
  36. data/test/invoker_test.rb +47 -0
  37. data/test/lexer_test.rb +172 -0
  38. data/test/links_test.rb +28 -0
  39. data/test/lists_test.rb +172 -13
  40. data/test/options_test.rb +29 -2
  41. data/test/paragraphs_test.rb +105 -47
  42. data/test/paths_test.rb +3 -3
  43. data/test/reader_test.rb +46 -0
  44. data/test/sections_test.rb +365 -12
  45. data/test/substitutions_test.rb +127 -11
  46. data/test/tables_test.rb +81 -14
  47. data/test/test_helper.rb +18 -7
  48. data/test/text_test.rb +17 -5
  49. metadata +9 -36
@@ -44,12 +44,6 @@ class Table < AbstractBlock
44
44
  }
45
45
  }
46
46
 
47
- # Public: A compiled Regexp to match a blank line
48
- BLANK_LINE_PATTERN = /\n[[:blank:]]*\n/
49
-
50
- # Public: Get/Set the String caption (unused, necessary for compatibility w/ next_block)
51
- attr_accessor :caption
52
-
53
47
  # Public: Get/Set the columns for this table
54
48
  attr_accessor :columns
55
49
 
@@ -57,23 +51,24 @@ class Table < AbstractBlock
57
51
  # and body rows)
58
52
  attr_accessor :rows
59
53
 
54
+ # Public: Boolean specifies whether this table has a header row
55
+ attr_reader :header_option
56
+
60
57
  def initialize(parent, attributes)
61
58
  super(parent, :table)
62
- # QUESTION since caption is on block, should it go to AbstractBlock?
63
- @caption = nil
64
59
  @rows = Rows.new([], [], [])
65
60
  @columns = []
66
61
 
67
- unless @attributes.has_key? 'tablepcwidth'
68
- # smell like we need a utility method here
69
- # to resolve an integer width from potential bogus input
70
- pcwidth = attributes['width']
71
- pcwidth_intval = pcwidth.to_i.abs
72
- if pcwidth_intval == 0 && pcwidth != "0" || pcwidth_intval > 100
73
- pcwidth_intval = 100
74
- end
75
- @attributes['tablepcwidth'] = pcwidth_intval
62
+ @has_header_option = attributes.has_key? 'header-option'
63
+
64
+ # smell like we need a utility method here
65
+ # to resolve an integer width from potential bogus input
66
+ pcwidth = attributes['width']
67
+ pcwidth_intval = pcwidth.to_i.abs
68
+ if pcwidth_intval == 0 && pcwidth != "0" || pcwidth_intval > 100
69
+ pcwidth_intval = 100
76
70
  end
71
+ @attributes['tablepcwidth'] = pcwidth_intval
77
72
 
78
73
  if @document.attributes.has_key? 'pagewidth'
79
74
  @attributes['tableabswidth'] ||=
@@ -81,6 +76,12 @@ class Table < AbstractBlock
81
76
  end
82
77
  end
83
78
 
79
+ # Internal: Returns whether the current row being processed is
80
+ # the header row
81
+ def header_row?
82
+ @has_header_option && @rows.body.size == 0
83
+ end
84
+
84
85
  # Internal: Creates the Column objects from the column spec
85
86
  #
86
87
  # returns nothing
@@ -130,9 +131,6 @@ class Table < AbstractBlock
130
131
  # rendered and returned as content that can be included in the
131
132
  # parent block's template.
132
133
  def render
133
- Debug.debug { "Now attempting to render for table my own bad #{self}" }
134
- Debug.debug { "Parent is #{@parent}" }
135
- Debug.debug { "Renderer is #{renderer}" }
136
134
  @document.playback_attributes @attributes
137
135
  renderer.render('block_table', self)
138
136
  end
@@ -154,6 +152,9 @@ class Table::Column < AbstractNode
154
152
  update_attributes(attributes)
155
153
  end
156
154
 
155
+ # Public: An alias to the parent block (which is always a Table)
156
+ alias :table :parent
157
+
157
158
  # Internal: Calculate and assign the widths (percentage and absolute) for this column
158
159
  #
159
160
  # This method assigns the colpcwidth and colabswidth attributes.
@@ -209,14 +210,19 @@ class Table::Cell < AbstractNode
209
210
  end
210
211
  update_attributes(attributes)
211
212
  end
212
- if @attributes['style'] == :asciidoc
213
+ # only allow AsciiDoc cells in non-header rows
214
+ if @attributes['style'] == :asciidoc && !column.table.header_row?
215
+ # FIXME hide doctitle from nested document; temporary workaround to fix
216
+ # nested document seeing doctitle and assuming it has its own document title
217
+ parent_doctitle = @document.attributes.delete('doctitle')
213
218
  @inner_document = Document.new(@text, :header_footer => false, :parent => @document)
219
+ @document.attributes['doctitle'] = parent_doctitle unless parent_doctitle.nil?
214
220
  end
215
221
  end
216
222
 
217
223
  # Public: Get the text with normal substitutions applied for this cell. Used for cells in the head rows
218
224
  def text
219
- apply_normal_subs(@text)
225
+ apply_normal_subs(@text).strip
220
226
  end
221
227
 
222
228
  # Public: Handles the body data (tbody, tfoot), applying styles and partitioning into paragraphs
@@ -225,7 +231,7 @@ class Table::Cell < AbstractNode
225
231
  if style == :asciidoc
226
232
  @inner_document.render
227
233
  else
228
- text.split(Table::BLANK_LINE_PATTERN).map {|p|
234
+ text.split(BLANK_LINE_PATTERN).map {|p|
229
235
  !style || style == :header ? p : Inline.new(parent, :quoted, p, :type => attr('style')).render
230
236
  }
231
237
  end
@@ -314,7 +320,7 @@ class Table::ParserContext
314
320
  #
315
321
  # returns the String after the match
316
322
  def skip_matched_delimiter(match, escaped = false)
317
- @buffer << (escaped ? match.pre_match.chop : match.pre_match) << @delimiter
323
+ @buffer = %(#@buffer#{escaped ? match.pre_match.chop : match.pre_match}#@delimiter)
318
324
  match.post_match
319
325
  end
320
326
 
@@ -1,3 +1,3 @@
1
1
  module Asciidoctor
2
- VERSION = '0.1.2'
2
+ VERSION = '0.1.3'
3
3
  end
data/man/asciidoctor.1 CHANGED
@@ -2,12 +2,12 @@
2
2
  .\" Title: asciidoctor
3
3
  .\" Author: [see the "AUTHORS" section]
4
4
  .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
5
- .\" Date: 04/25/2013
5
+ .\" Date: 05/30/2013
6
6
  .\" Manual: \ \&
7
7
  .\" Source: \ \&
8
8
  .\" Language: English
9
9
  .\"
10
- .TH "ASCIIDOCTOR" "1" "04/25/2013" "\ \&" "\ \&"
10
+ .TH "ASCIIDOCTOR" "1" "05/30/2013" "\ \&" "\ \&"
11
11
  .\" -----------------------------------------------------------------
12
12
  .\" * Define some portability stuff
13
13
  .\" -----------------------------------------------------------------
@@ -71,20 +71,22 @@ when Asciidoctor is invoked using this script\&.
71
71
  Define, override or delete a document attribute\&. Command\-line attributes take precedence over attributes defined in the source file\&.
72
72
  .sp
73
73
  \fIATTRIBUTE\fR
74
- is formatted as a key\-value pair, in the form
75
- \fINAME=VALUE\fR\&. Values containing spaces should be enclosed in double\-quote characters\&. Alternate acceptable forms are
74
+ is normally formatted as a key\-value pair, in the form
75
+ \fINAME=VALUE\fR\&. Alternate acceptable forms are
76
76
  \fINAME\fR
77
- (the
77
+ (where the
78
78
  \fIVALUE\fR
79
79
  defaults to an empty string),
80
80
  \fINAME!\fR
81
- (deletes the
81
+ (unassigns the
82
82
  \fINAME\fR
83
83
  attribute) and
84
84
  \fINAME=VALUE@\fR
85
- (does not override
85
+ (where
86
+ \fIVALUE\fR
87
+ does not override value of
86
88
  \fINAME\fR
87
- attribute if already defined in the source file)\&.
89
+ attribute if it\(cqs already defined in the source document)\&. Values containing spaces should be enclosed in quotes\&.
88
90
  .sp
89
91
  This option may be specified more than once\&.
90
92
  .RE
@@ -94,28 +96,32 @@ This option may be specified more than once\&.
94
96
  Backend output file format:
95
97
  \fIdocbook45\fR
96
98
  or
97
- \fIhtml5\fR\&. You can also use the backend alias names
99
+ \fIhtml5\fR
100
+ supported out of the box\&. You can also use the backend alias names
98
101
  \fIhtml\fR
99
102
  (aliased to
100
103
  \fIhtml5\fR) or
101
104
  \fIdocbook\fR
102
105
  (aliased to
103
106
  \fIdocbook45\fR)\&. Defaults to
104
- \fIhtml5\fR\&.
107
+ \fIhtml5\fR\&. Other options can be passed, but if Asciidoctor cannot find the backend, it will fail during rendering\&.
105
108
  .RE
106
109
  .PP
107
110
  \fB\-d, \-\-doctype\fR=\fIDOCTYPE\fR
108
111
  .RS 4
109
112
  Document type:
110
- \fIarticle\fR
113
+ \fIarticle\fR,
114
+ \fIbook\fR
111
115
  or
112
- \fIbook\fR\&. Sets the root element when using the
116
+ \fIinline\fR\&. Sets the root element when using the
113
117
  \fIdocbook\fR
114
118
  backend and the style class on the HTML body element when using the
115
119
  \fIhtml\fR
116
120
  backend\&. The
117
121
  \fIbook\fR
118
- document type allows multiple level\-0 section titles in a single document\&. Defaults to
122
+ document type allows multiple level\-0 section titles in a single document\&. The
123
+ \fIinline\fR
124
+ document type allows the content of a single paragraph to be formatted and returned without wrapping it in a containing element\&. Defaults to
119
125
  \fIarticle\fR\&.
120
126
  .RE
121
127
  .SS "Rendering Control"
@@ -164,7 +170,7 @@ Suppress the document header and footer in the output\&.
164
170
  .PP
165
171
  \fB\-T, \-\-template\-dir\fR=\fIDIR\fR
166
172
  .RS 4
167
- Directory containing custom render templates that override one or more templates from the the built\-in set\&. If there is a folder in the directory that matches the backend, the templates from that folder will be used\&.
173
+ Directory containing custom render templates that override one or more templates from the built\-in set\&. If there is a folder in the directory that matches the backend, the templates from that folder will be used\&.
168
174
  .RE
169
175
  .SS "Processing Information"
170
176
  .PP
@@ -204,7 +210,7 @@ Failure (syntax or usage error; configuration error; document processing failure
204
210
  See the \fBAsciidoctor\fR issue tracker: <\fBhttps://github\&.com/asciidoctor/asciidoctor/issues?state=open\fR>
205
211
  .SH "AUTHORS"
206
212
  .sp
207
- \fBAsciidoctor\fR was written by Ryan Waldron, Dan Allen and other contributors\&.
213
+ \fBAsciidoctor\fR was written by Dan Allen, Ryan Waldron, Jason Porter, Nick Hengeveld and other contributors\&.
208
214
  .sp
209
215
  \fBAsciiDoc\fR was written by Stuart Rackham and has received contributions from many other individuals\&.
210
216
  .SH "RESOURCES"
@@ -218,4 +224,4 @@ GitHub organization: <\fBhttp://github\&.com/asciidoctor\fR>
218
224
  Mailinglist / forum: <\fBhttp://discuss\&.asciidoctor\&.org\fR>
219
225
  .SH "COPYING"
220
226
  .sp
221
- Copyright (C) Ryan Waldron and Dan Allen\&. Free use of this software is granted under the terms of the MIT License\&.
227
+ Copyright (C) 2012\-2013 Dan Allen and Ryan Waldron\&. Free use of this software is granted under the terms of the MIT License\&.
data/man/asciidoctor.ad CHANGED
@@ -1,6 +1,7 @@
1
1
  asciidoctor(1)
2
2
  ==============
3
3
  :doctype: manpage
4
+ :awestruct-layout: base
4
5
 
5
6
 
6
7
  NAME
@@ -52,24 +53,28 @@ Document Settings
52
53
  Define, override or delete a document attribute. Command-line attributes
53
54
  take precedence over attributes defined in the source file.
54
55
  +
55
- 'ATTRIBUTE' is formatted as a key-value pair, in the form 'NAME=VALUE'. Values
56
- containing spaces should be enclosed in double-quote characters. Alternate
57
- acceptable forms are 'NAME' (the 'VALUE' defaults to an empty string), 'NAME!'
58
- (deletes the 'NAME' attribute) and 'NAME=VALUE@' (does not override 'NAME'
59
- attribute if already defined in the source file).
56
+ 'ATTRIBUTE' is normally formatted as a key-value pair, in the form 'NAME=VALUE'.
57
+ Alternate acceptable forms are 'NAME' (where the 'VALUE' defaults to an empty
58
+ string), 'NAME!' (unassigns the 'NAME' attribute) and 'NAME=VALUE@' (where
59
+ 'VALUE' does not override value of 'NAME' attribute if it's already defined in
60
+ the source document). Values containing spaces should be enclosed in quotes.
60
61
  +
61
62
  This option may be specified more than once.
62
63
 
63
64
  *-b, --backend*='BACKEND'::
64
- Backend output file format: 'docbook45' or 'html5'. You can also use the
65
- backend alias names 'html' (aliased to 'html5') or 'docbook' (aliased to
66
- 'docbook45'). Defaults to 'html5'.
65
+ Backend output file format: 'docbook45' or 'html5' supported out of the box.
66
+ You can also use the backend alias names 'html' (aliased to 'html5') or
67
+ 'docbook' (aliased to 'docbook45'). Defaults to 'html5'. Other options can
68
+ be passed, but if Asciidoctor cannot find the backend, it will fail during
69
+ rendering.
67
70
 
68
71
  *-d, --doctype*='DOCTYPE'::
69
- Document type: 'article' or 'book'. Sets the root element when using the
70
- 'docbook' backend and the style class on the HTML body element when using
71
- the 'html' backend. The 'book' document type allows multiple level-0
72
- section titles in a single document. Defaults to 'article'.
72
+ Document type: 'article', 'book' or 'inline'. Sets the root element when
73
+ using the 'docbook' backend and the style class on the HTML body element
74
+ when using the 'html' backend. The 'book' document type allows multiple
75
+ level-0 section titles in a single document. The 'inline' document type
76
+ allows the content of a single paragraph to be formatted and returned
77
+ without wrapping it in a containing element. Defaults to 'article'.
73
78
 
74
79
  Rendering Control
75
80
  ~~~~~~~~~~~~~~~~~
@@ -101,7 +106,7 @@ Rendering Control
101
106
 
102
107
  *-T, --template-dir*='DIR'::
103
108
  Directory containing custom render templates that override one or more
104
- templates from the the built-in set. If there is a folder in the directory
109
+ templates from the built-in set. If there is a folder in the directory
105
110
  that matches the backend, the templates from that folder will be used.
106
111
 
107
112
  Processing Information
@@ -141,7 +146,8 @@ See the *Asciidoctor* issue tracker: <**https://github.com/asciidoctor/asciidoct
141
146
 
142
147
  AUTHORS
143
148
  -------
144
- *Asciidoctor* was written by Ryan Waldron, Dan Allen and other contributors.
149
+ *Asciidoctor* was written by Dan Allen, Ryan Waldron, Jason Porter, Nick
150
+ Hengeveld and other contributors.
145
151
 
146
152
  *AsciiDoc* was written by Stuart Rackham and has received contributions from
147
153
  many other individuals.
@@ -160,5 +166,7 @@ Mailinglist / forum: <**http://discuss.asciidoctor.org**>
160
166
 
161
167
  COPYING
162
168
  -------
163
- Copyright \(C) Ryan Waldron and Dan Allen. Free use of this software is granted
164
- under the terms of the MIT License.
169
+ Copyright \(C) 2012-2013 Dan Allen and Ryan Waldron. Free use of this
170
+ software is granted under the terms of the MIT License.
171
+
172
+ // vim: tw=80
@@ -332,6 +332,34 @@ of the attribute named foo in your document.
332
332
  assert_xpath %(//li[1]/p[text()="docdir: #{docdir}"]), output, 1
333
333
  assert_xpath %(//li[2]/p[text()="docfile: #{docfile}"]), output, 1
334
334
  end
335
+
336
+ test 'assigns attribute defined in attribute reference with set prefix and value' do
337
+ input = '{set:foo:bar}{foo}'
338
+ output = render_embedded_string input
339
+ assert_xpath '//p', output, 1
340
+ assert_xpath '//p[text()="bar"]', output, 1
341
+ end
342
+
343
+ test 'assigns attribute defined in attribute reference with set prefix and no value' do
344
+ input = "{set:foo}\n{foo}yes"
345
+ output = render_embedded_string input
346
+ assert_xpath '//p', output, 1
347
+ assert_xpath '//p[normalize-space(text())="yes"]', output, 1
348
+ end
349
+
350
+ test 'assigns attribute defined in attribute reference with set prefix and empty value' do
351
+ input = "{set:foo:}\n{foo}yes"
352
+ output = render_embedded_string input
353
+ assert_xpath '//p', output, 1
354
+ assert_xpath '//p[normalize-space(text())="yes"]', output, 1
355
+ end
356
+
357
+ test 'unassigns attribute defined in attribute reference with set prefix' do
358
+ input = ":foo:\n\n{set:foo!}\n{foo}yes"
359
+ output = render_embedded_string input
360
+ assert_xpath '//p', output, 1
361
+ assert_xpath '//p/child::text()', output, 0
362
+ end
335
363
  end
336
364
 
337
365
  context "Intrinsic attributes" do
@@ -531,6 +559,28 @@ A paragraph
531
559
  assert_equal 'lead', para.attributes['role']
532
560
  end
533
561
 
562
+ test 'id and role attributes can be specified on block style using shorthand syntax' do
563
+ input = <<-EOS
564
+ [normal#first.lead]
565
+ A normal paragraph.
566
+ EOS
567
+ doc = document_from_string(input)
568
+ para = doc.blocks.first
569
+ assert_equal 'first', para.attributes['id']
570
+ assert_equal 'lead', para.attributes['role']
571
+ end
572
+
573
+ test 'id and role attributes can be specified on section style using shorthand syntax' do
574
+ input = <<-EOS
575
+ [dedication#dedication.small]
576
+ == Section
577
+ Content.
578
+ EOS
579
+ output = render_embedded_string input
580
+ assert_xpath '/div[@class="sect1 small"]', output, 1
581
+ assert_xpath '/div[@class="sect1 small"]/h2[@id="dedication"]', output, 1
582
+ end
583
+
534
584
  test "Block attributes are additive" do
535
585
  input = <<-EOS
536
586
  [id='foo']
data/test/blocks_test.rb CHANGED
@@ -117,6 +117,252 @@ block comment
117
117
  end
118
118
  end
119
119
 
120
+ context 'Quote and Verse Blocks' do
121
+ test 'quote block with no attribution' do
122
+ input = <<-EOS
123
+ ____
124
+ A famous quote.
125
+ ____
126
+ EOS
127
+ output = render_string input
128
+ assert_css '.quoteblock', output, 1
129
+ assert_css '.quoteblock > blockquote', output, 1
130
+ assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
131
+ assert_css '.quoteblock > .attribution', output, 0
132
+ assert_xpath '//*[@class = "quoteblock"]//p[text() = "A famous quote."]', output, 1
133
+ end
134
+
135
+ test 'quote block with attribution' do
136
+ input = <<-EOS
137
+ [quote, Famous Person, Famous Book (1999)]
138
+ ____
139
+ A famous quote.
140
+ ____
141
+ EOS
142
+ output = render_string input
143
+ assert_css '.quoteblock', output, 1
144
+ assert_css '.quoteblock > blockquote', output, 1
145
+ assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
146
+ assert_css '.quoteblock > .attribution', output, 1
147
+ assert_css '.quoteblock > .attribution > cite', output, 1
148
+ assert_css '.quoteblock > .attribution > cite + br', output, 1
149
+ assert_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]/cite[text() = "Famous Book (1999)"]', output, 1
150
+ attribution = xmlnodes_at_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]', output, 1
151
+ author = attribution.children.last
152
+ assert_equal "#{expand_entity 8212} Famous Person", author.text.strip
153
+ end
154
+
155
+ test 'quote block with attribute and id and role shorthand' do
156
+ input = <<-EOS
157
+ [quote#think.big, Donald Trump]
158
+ ____
159
+ As long as your going to be thinking anyway, think big.
160
+ ____
161
+ EOS
162
+
163
+ output = render_embedded_string input
164
+ assert_css '.quoteblock', output, 1
165
+ assert_css '#think.quoteblock.big', output, 1
166
+ assert_css '.quoteblock > .attribution', output, 1
167
+ end
168
+
169
+ test 'quote block with complex content' do
170
+ input = <<-EOS
171
+ ____
172
+ A famous quote.
173
+
174
+ NOTE: _That_ was inspiring.
175
+ ____
176
+ EOS
177
+ output = render_string input
178
+ assert_css '.quoteblock', output, 1
179
+ assert_css '.quoteblock > blockquote', output, 1
180
+ assert_css '.quoteblock > blockquote > .paragraph', output, 1
181
+ assert_css '.quoteblock > blockquote > .paragraph + .admonitionblock', output, 1
182
+ end
183
+
184
+ test 'quote block using air quotes with no attribution' do
185
+ input = <<-EOS
186
+ ""
187
+ A famous quote.
188
+ ""
189
+ EOS
190
+ output = render_string input
191
+ assert_css '.quoteblock', output, 1
192
+ assert_css '.quoteblock > blockquote', output, 1
193
+ assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
194
+ assert_css '.quoteblock > .attribution', output, 0
195
+ assert_xpath '//*[@class = "quoteblock"]//p[text() = "A famous quote."]', output, 1
196
+ end
197
+
198
+ test 'markdown-style quote block with single paragraph and no attribution' do
199
+ input = <<-EOS
200
+ > A famous quote.
201
+ > Some more inspiring words.
202
+ EOS
203
+ output = render_string input
204
+ assert_css '.quoteblock', output, 1
205
+ assert_css '.quoteblock > blockquote', output, 1
206
+ assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
207
+ assert_css '.quoteblock > .attribution', output, 0
208
+ assert_xpath %(//*[@class = "quoteblock"]//p[text() = "A famous quote.\nSome more inspiring words."]), output, 1
209
+ end
210
+
211
+ test 'lazy markdown-style quote block with single paragraph and no attribution' do
212
+ input = <<-EOS
213
+ > A famous quote.
214
+ Some more inspiring words.
215
+ EOS
216
+ output = render_string input
217
+ assert_css '.quoteblock', output, 1
218
+ assert_css '.quoteblock > blockquote', output, 1
219
+ assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
220
+ assert_css '.quoteblock > .attribution', output, 0
221
+ assert_xpath %(//*[@class = "quoteblock"]//p[text() = "A famous quote.\nSome more inspiring words."]), output, 1
222
+ end
223
+
224
+ test 'markdown-style quote block with multiple paragraphs and no attribution' do
225
+ input = <<-EOS
226
+ > A famous quote.
227
+ >
228
+ > Some more inspiring words.
229
+ EOS
230
+ output = render_string input
231
+ assert_css '.quoteblock', output, 1
232
+ assert_css '.quoteblock > blockquote', output, 1
233
+ assert_css '.quoteblock > blockquote > .paragraph > p', output, 2
234
+ assert_css '.quoteblock > .attribution', output, 0
235
+ assert_xpath %((//*[@class = "quoteblock"]//p)[1][text() = "A famous quote."]), output, 1
236
+ assert_xpath %((//*[@class = "quoteblock"]//p)[2][text() = "Some more inspiring words."]), output, 1
237
+ end
238
+
239
+ test 'markdown-style quote block with multiple blocks and no attribution' do
240
+ input = <<-EOS
241
+ > A famous quote.
242
+ >
243
+ > NOTE: Some more inspiring words.
244
+ EOS
245
+ output = render_string input
246
+ assert_css '.quoteblock', output, 1
247
+ assert_css '.quoteblock > blockquote', output, 1
248
+ assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
249
+ assert_css '.quoteblock > blockquote > .admonitionblock', output, 1
250
+ assert_css '.quoteblock > .attribution', output, 0
251
+ assert_xpath %((//*[@class = "quoteblock"]//p)[1][text() = "A famous quote."]), output, 1
252
+ assert_xpath %((//*[@class = "quoteblock"]//*[@class = "admonitionblock note"]//*[@class="content"])[1][normalize-space(text()) = "Some more inspiring words."]), output, 1
253
+ end
254
+
255
+ test 'markdown-style quote block with single paragraph and attribution' do
256
+ input = <<-EOS
257
+ > A famous quote.
258
+ > Some more inspiring words.
259
+ > -- Famous Person, Famous Source (1999)
260
+ EOS
261
+ output = render_string input
262
+ assert_css '.quoteblock', output, 1
263
+ assert_css '.quoteblock > blockquote', output, 1
264
+ assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
265
+ assert_xpath %(//*[@class = "quoteblock"]//p[text() = "A famous quote.\nSome more inspiring words."]), output, 1
266
+ assert_css '.quoteblock > .attribution', output, 1
267
+ assert_css '.quoteblock > .attribution > cite', output, 1
268
+ assert_css '.quoteblock > .attribution > cite + br', output, 1
269
+ assert_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]/cite[text() = "Famous Source (1999)"]', output, 1
270
+ attribution = xmlnodes_at_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]', output, 1
271
+ author = attribution.children.last
272
+ assert_equal "#{expand_entity 8212} Famous Person", author.text.strip
273
+ end
274
+
275
+ test 'quoted paragraph-style quote block with attribution' do
276
+ input = <<-EOS
277
+ "A famous quote.
278
+ Some more inspiring words."
279
+ -- Famous Person, Famous Source (1999)
280
+ EOS
281
+ output = render_string input
282
+ assert_css '.quoteblock', output, 1
283
+ assert_css '.quoteblock > blockquote', output, 1
284
+ assert_xpath %(//*[@class = "quoteblock"]/blockquote[normalize-space(text()) = "A famous quote. Some more inspiring words."]), output, 1
285
+ assert_css '.quoteblock > .attribution', output, 1
286
+ assert_css '.quoteblock > .attribution > cite', output, 1
287
+ assert_css '.quoteblock > .attribution > cite + br', output, 1
288
+ assert_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]/cite[text() = "Famous Source (1999)"]', output, 1
289
+ attribution = xmlnodes_at_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]', output, 1
290
+ author = attribution.children.last
291
+ assert_equal "#{expand_entity 8212} Famous Person", author.text.strip
292
+ end
293
+
294
+ test 'single-line verse block without attribution' do
295
+ input = <<-EOS
296
+ [verse]
297
+ ____
298
+ A famous verse.
299
+ ____
300
+ EOS
301
+ output = render_string input
302
+ assert_css '.verseblock', output, 1
303
+ assert_css '.verseblock > pre', output, 1
304
+ assert_css '.verseblock > .attribution', output, 0
305
+ assert_css '.verseblock p', output, 0
306
+ assert_xpath '//*[@class = "verseblock"]/pre[normalize-space(text()) = "A famous verse."]', output, 1
307
+ end
308
+
309
+ test 'single-line verse block with attribution' do
310
+ input = <<-EOS
311
+ [verse, Famous Poet, Famous Poem]
312
+ ____
313
+ A famous verse.
314
+ ____
315
+ EOS
316
+ output = render_string input
317
+ assert_css '.verseblock', output, 1
318
+ assert_css '.verseblock p', output, 0
319
+ assert_css '.verseblock > pre', output, 1
320
+ assert_css '.verseblock > .attribution', output, 1
321
+ assert_css '.verseblock > .attribution > cite', output, 1
322
+ assert_css '.verseblock > .attribution > cite + br', output, 1
323
+ assert_xpath '//*[@class = "verseblock"]/*[@class = "attribution"]/cite[text() = "Famous Poem"]', output, 1
324
+ attribution = xmlnodes_at_xpath '//*[@class = "verseblock"]/*[@class = "attribution"]', output, 1
325
+ author = attribution.children.last
326
+ assert_equal "#{expand_entity 8212} Famous Poet", author.text.strip
327
+ end
328
+
329
+ test 'multi-stanza verse block' do
330
+ input = <<-EOS
331
+ [verse]
332
+ ____
333
+ A famous verse.
334
+
335
+ Stanza two.
336
+ ____
337
+ EOS
338
+ output = render_string input
339
+ assert_xpath '//*[@class = "verseblock"]', output, 1
340
+ assert_xpath '//*[@class = "verseblock"]/pre', output, 1
341
+ assert_xpath '//*[@class = "verseblock"]//p', output, 0
342
+ assert_xpath '//*[@class = "verseblock"]/pre[contains(text(), "A famous verse.")]', output, 1
343
+ assert_xpath '//*[@class = "verseblock"]/pre[contains(text(), "Stanza two.")]', output, 1
344
+ end
345
+
346
+ test 'verse block does not contain block elements' do
347
+ input = <<-EOS
348
+ [verse]
349
+ ____
350
+ A famous verse.
351
+
352
+ ....
353
+ not a literal
354
+ ....
355
+ ____
356
+ EOS
357
+ output = render_string input
358
+ assert_css '.verseblock', output, 1
359
+ assert_css '.verseblock > pre', output, 1
360
+ assert_css '.verseblock p', output, 0
361
+ assert_css '.verseblock .literalblock', output, 0
362
+ end
363
+
364
+ end
365
+
120
366
  context "Example Blocks" do
121
367
  test "can render example block" do
122
368
  input = <<-EOS
@@ -198,6 +444,20 @@ You just write.
198
444
  assert !doc.attributes.has_key?('example-number')
199
445
  end
200
446
 
447
+ test 'explicit caption is set on block even if block has no title' do
448
+ input = <<-EOS
449
+ [caption="Look!"]
450
+ ====
451
+ Just write.
452
+ ====
453
+ EOS
454
+
455
+ doc = document_from_string input
456
+ assert_equal 'Look!', doc.blocks.first.caption
457
+ output = doc.render
458
+ assert_no_match(/Look/, output)
459
+ end
460
+
201
461
  test 'automatic caption can be turned off and on and modified' do
202
462
  input = <<-EOS
203
463
  .first example
@@ -400,6 +660,60 @@ source line 2\r
400
660
  assert_xpath %(/*[@class="listingblock"]//pre/code[text()="source line 1\nsource line 2"]), output, 1
401
661
  end
402
662
 
663
+ test 'should remove block indent if indent attribute is 0' do
664
+ input = <<-EOS
665
+ [indent="0"]
666
+ ----
667
+ def names
668
+
669
+ @names.split ' '
670
+
671
+ end
672
+ ----
673
+ EOS
674
+
675
+ expected = <<-EOS
676
+ def names
677
+
678
+ @names.split ' '
679
+
680
+ end
681
+ EOS
682
+
683
+ output = render_embedded_string input
684
+ assert_css 'pre', output, 1
685
+ assert_css '.listingblock pre', output, 1
686
+ result = xmlnodes_at_xpath('//pre', output, 1).text
687
+ assert_equal expected.chomp, result
688
+ end
689
+
690
+ test 'should set block indent to value specified by indent attribute' do
691
+ input = <<-EOS
692
+ [indent="1"]
693
+ ----
694
+ def names
695
+
696
+ @names.split ' '
697
+
698
+ end
699
+ ----
700
+ EOS
701
+
702
+ expected = <<-EOS
703
+ def names
704
+
705
+ @names.split ' '
706
+
707
+ end
708
+ EOS
709
+
710
+ output = render_embedded_string input
711
+ assert_css 'pre', output, 1
712
+ assert_css '.listingblock pre', output, 1
713
+ result = xmlnodes_at_xpath('//pre', output, 1).text
714
+ assert_equal expected.chomp, result
715
+ end
716
+
403
717
  test 'literal block should honor explicit subs list' do
404
718
  input = <<-EOS
405
719
  [subs="verbatim,quotes"]
@@ -447,6 +761,58 @@ AssertionError
447
761
  # so rstrip is necessary
448
762
  assert_equal output.rstrip, output2.rstrip
449
763
  end
764
+
765
+ test 'listing block without title should generate screen element in docbook' do
766
+ input = <<-EOS
767
+ ----
768
+ listing block
769
+ ----
770
+ EOS
771
+
772
+ output = render_embedded_string input, :backend => 'docbook'
773
+ assert_xpath '/screen[text()="listing block"]', output, 1
774
+ end
775
+
776
+ test 'listing block with title should generate screen element inside formalpara element in docbook' do
777
+ input = <<-EOS
778
+ .title
779
+ ----
780
+ listing block
781
+ ----
782
+ EOS
783
+
784
+ output = render_embedded_string input, :backend => 'docbook'
785
+ assert_xpath '/formalpara', output, 1
786
+ assert_xpath '/formalpara/title[text()="title"]', output, 1
787
+ assert_xpath '/formalpara/para/screen[text()="listing block"]', output, 1
788
+ end
789
+
790
+ test 'source block with no title or language should generate screen element in docbook' do
791
+ input = <<-EOS
792
+ [source]
793
+ ----
794
+ listing block
795
+ ----
796
+ EOS
797
+
798
+ output = render_embedded_string input, :backend => 'docbook'
799
+ assert_xpath '/screen[text()="listing block"]', output, 1
800
+ end
801
+
802
+ test 'source block with title and no language should generate screen element inside formalpara element in docbook' do
803
+ input = <<-EOS
804
+ [source]
805
+ .title
806
+ ----
807
+ listing block
808
+ ----
809
+ EOS
810
+
811
+ output = render_embedded_string input, :backend => 'docbook'
812
+ assert_xpath '/formalpara', output, 1
813
+ assert_xpath '/formalpara/title[text()="title"]', output, 1
814
+ assert_xpath '/formalpara/para/screen[text()="listing block"]', output, 1
815
+ end
450
816
  end
451
817
 
452
818
  context "Open Blocks" do
@@ -542,15 +908,25 @@ paragraph
542
908
  assert_xpath '//*[@class="paragraph"]/p[text() = "paragraph"]', output, 1
543
909
  end
544
910
 
545
- test 'block title above document title gets carried over to preamble' do
911
+ test 'block title above document title demotes document title to a section title' do
546
912
  input = <<-EOS
547
913
  .Block title
548
- = Document Title
549
-
550
- preamble
551
- EOS
552
- output = render_string input
553
- assert_xpath '//*[@id="preamble"]//*[@class="paragraph"]/*[@class="title"][text()="Block title"]', output, 1
914
+ = Section Title
915
+
916
+ section paragraph
917
+ EOS
918
+ output, errors = nil
919
+ redirect_streams do |stdout, stderr|
920
+ output = render_string input
921
+ errors = stdout.string
922
+ end
923
+ assert_xpath '//*[@id="header"]/*', output, 0
924
+ assert_xpath '//*[@id="preamble"]/*', output, 0
925
+ assert_xpath '//*[@id="content"]/h1[text()="Section Title"]', output, 1
926
+ assert_xpath '//*[@class="paragraph"]', output, 1
927
+ assert_xpath '//*[@class="paragraph"]/*[@class="title"][text()="Block title"]', output, 1
928
+ assert !errors.empty?
929
+ assert_match(/only book doctypes can contain level 0 sections/, errors)
554
930
  end
555
931
 
556
932
  test 'block title above document title gets carried over to first block in first section if no preamble' do
@@ -959,6 +1335,18 @@ You can use icons for admonitions by setting the 'icons' attribute.
959
1335
  output = render_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)}
960
1336
  assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Tip"]', output, 1
961
1337
  end
1338
+
1339
+ test 'can use font-based icons' do
1340
+ input = <<-EOS
1341
+ :icons: font
1342
+
1343
+ [TIP]
1344
+ You can use icons for admonitions by setting the 'icons' attribute.
1345
+ EOS
1346
+
1347
+ output = render_string input, :safe => Asciidoctor::SafeMode::SERVER
1348
+ assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/i[@class="icon-tip"]', output, 1
1349
+ end
962
1350
  end
963
1351
 
964
1352
  context 'Image paths' do
@@ -1050,7 +1438,7 @@ html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table)
1050
1438
  ----
1051
1439
  EOS
1052
1440
  output = render_string input, :safe => Asciidoctor::SafeMode::SAFE
1053
- assert_xpath '//pre[@class="highlight CodeRay"]/code[@class="ruby"]//span[@class = "constant"][text() = "CodeRay"]', output, 1
1441
+ assert_xpath '//pre[@class="CodeRay"]/code[@class="ruby language-ruby"]//span[@class = "constant"][text() = "CodeRay"]', output, 1
1054
1442
  assert_match(/\.CodeRay \{/, output)
1055
1443
  end
1056
1444
 
@@ -1067,7 +1455,7 @@ html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table)
1067
1455
  ----
1068
1456
  EOS
1069
1457
  output = render_string input, :safe => Asciidoctor::SafeMode::SAFE
1070
- assert_xpath '//pre[@class="highlight CodeRay"]/code[@class="ruby"]//span[@style = "color:#036;font-weight:bold"][text() = "CodeRay"]', output, 1
1458
+ assert_xpath '//pre[@class="CodeRay"]/code[@class="ruby language-ruby"]//span[@style = "color:#036;font-weight:bold"][text() = "CodeRay"]', output, 1
1071
1459
  assert_no_match(/\.CodeRay \{/, output)
1072
1460
  end
1073
1461
 
@@ -1097,4 +1485,267 @@ html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table)
1097
1485
  end
1098
1486
  end
1099
1487
 
1488
+ context 'Abstract and Part Intro' do
1489
+ test 'should make abstract on open block without title a quote block for article' do
1490
+ input = <<-EOS
1491
+ = Article
1492
+
1493
+ [abstract]
1494
+ --
1495
+ This article is about stuff.
1496
+
1497
+ And other stuff.
1498
+ --
1499
+ EOS
1500
+
1501
+ output = render_string input
1502
+ assert_css '.quoteblock', output, 1
1503
+ assert_css '.quoteblock.abstract', output, 1
1504
+ assert_css '#preamble .quoteblock', output, 1
1505
+ assert_css '.quoteblock > blockquote', output, 1
1506
+ assert_css '.quoteblock > blockquote > .paragraph', output, 2
1507
+ end
1508
+
1509
+ test 'should make abstract on open block with title a quote block with title for article' do
1510
+ input = <<-EOS
1511
+ = Article
1512
+
1513
+ .My abstract
1514
+ [abstract]
1515
+ --
1516
+ This article is about stuff.
1517
+ --
1518
+ EOS
1519
+
1520
+ output = render_string input
1521
+ assert_css '.quoteblock', output, 1
1522
+ assert_css '.quoteblock.abstract', output, 1
1523
+ assert_css '#preamble .quoteblock', output, 1
1524
+ assert_css '.quoteblock > .title', output, 1
1525
+ assert_css '.quoteblock > .title + blockquote', output, 1
1526
+ assert_css '.quoteblock > .title + blockquote > .paragraph', output, 1
1527
+ end
1528
+
1529
+ test 'should allow abstract in document with title if doctype is book' do
1530
+ input = <<-EOS
1531
+ = Book
1532
+ :doctype: book
1533
+
1534
+ [abstract]
1535
+ Abstract for book with title is valid
1536
+ EOS
1537
+
1538
+ output = render_string input
1539
+ assert_css '.abstract', output, 1
1540
+ end
1541
+
1542
+ test 'should not allow abstract as direct child of document if doctype is book' do
1543
+ input = <<-EOS
1544
+ :doctype: book
1545
+
1546
+ [abstract]
1547
+ Abstract for book without title is invalid.
1548
+ EOS
1549
+
1550
+ output = render_string input
1551
+ assert_css '.abstract', output, 0
1552
+ end
1553
+
1554
+ test 'should make abstract on open block without title rendered to DocBook' do
1555
+ input = <<-EOS
1556
+ = Article
1557
+
1558
+ [abstract]
1559
+ --
1560
+ This article is about stuff.
1561
+
1562
+ And other stuff.
1563
+ --
1564
+ EOS
1565
+
1566
+ output = render_string input, :backend => 'docbook'
1567
+ assert_css 'abstract', output, 1
1568
+ assert_css 'abstract > simpara', output, 2
1569
+ end
1570
+
1571
+ test 'should make abstract on open block with title rendered to DocBook' do
1572
+ input = <<-EOS
1573
+ = Article
1574
+
1575
+ .My abstract
1576
+ [abstract]
1577
+ --
1578
+ This article is about stuff.
1579
+ --
1580
+ EOS
1581
+
1582
+ output = render_string input, :backend => 'docbook'
1583
+ assert_css 'abstract', output, 1
1584
+ assert_css 'abstract > title', output, 1
1585
+ assert_css 'abstract > title + simpara', output, 1
1586
+ end
1587
+
1588
+ test 'should allow abstract in document with title if doctype is book rendered to DocBook' do
1589
+ input = <<-EOS
1590
+ = Book
1591
+ :doctype: book
1592
+
1593
+ [abstract]
1594
+ Abstract for book with title is valid
1595
+ EOS
1596
+
1597
+ output = render_string input, :backend => 'docbook'
1598
+ assert_css 'abstract', output, 1
1599
+ end
1600
+
1601
+ test 'should not allow abstract as direct child of document if doctype is book rendered to DocBook' do
1602
+ input = <<-EOS
1603
+ :doctype: book
1604
+
1605
+ [abstract]
1606
+ Abstract for book is invalid.
1607
+ EOS
1608
+
1609
+ output = render_string input, :backend => 'docbook'
1610
+ assert_css 'abstract', output, 0
1611
+ end
1612
+
1613
+ # TODO partintro shouldn't be recognized if doctype is not book, should be in proper place
1614
+ test 'should accept partintro on open block without title' do
1615
+ input = <<-EOS
1616
+ = Book
1617
+ :doctype: book
1618
+
1619
+ = Part 1
1620
+
1621
+ [partintro]
1622
+ --
1623
+ This is a part intro.
1624
+
1625
+ It can have multiple paragraphs.
1626
+ --
1627
+ EOS
1628
+
1629
+ output = render_string input
1630
+ assert_css '.openblock', output, 1
1631
+ assert_css '.openblock.partintro', output, 1
1632
+ assert_css '.openblock .title', output, 0
1633
+ assert_css '.openblock .content', output, 1
1634
+ assert_xpath %(//h1[@id="_part_1"]/following-sibling::*[#{contains_class(:openblock)}]), output, 1
1635
+ assert_xpath %(//*[#{contains_class(:openblock)}]/*[@class="content"]/*[@class="paragraph"]), output, 2
1636
+ end
1637
+
1638
+ test 'should accept partintro on open block with title' do
1639
+ input = <<-EOS
1640
+ = Book
1641
+ :doctype: book
1642
+
1643
+ = Part 1
1644
+
1645
+ .Intro title
1646
+ [partintro]
1647
+ --
1648
+ This is a part intro with a title.
1649
+ --
1650
+ EOS
1651
+
1652
+ output = render_string input
1653
+ assert_css '.openblock', output, 1
1654
+ assert_css '.openblock.partintro', output, 1
1655
+ assert_css '.openblock .title', output, 1
1656
+ assert_css '.openblock .content', output, 1
1657
+ assert_xpath %(//h1[@id="_part_1"]/following-sibling::*[#{contains_class(:openblock)}]), output, 1
1658
+ assert_xpath %(//*[#{contains_class(:openblock)}]/*[@class="title"][text() = "Intro title"]), output, 1
1659
+ assert_xpath %(//*[#{contains_class(:openblock)}]/*[@class="content"]/*[@class="paragraph"]), output, 1
1660
+ end
1661
+
1662
+ test 'should exclude partintro if not a child of part' do
1663
+ input = <<-EOS
1664
+ = Book
1665
+ :doctype: book
1666
+
1667
+ [partintro]
1668
+ part intro paragraph
1669
+ EOS
1670
+
1671
+ output = render_string input
1672
+ assert_css '.partintro', output, 0
1673
+ end
1674
+
1675
+ test 'should not allow partintro unless doctype is book' do
1676
+ input = <<-EOS
1677
+ [partintro]
1678
+ part intro paragraph
1679
+ EOS
1680
+
1681
+ output = render_string input
1682
+ assert_css '.partintro', output, 0
1683
+ end
1684
+
1685
+ test 'should accept partintro on open block without title rendered to DocBook' do
1686
+ input = <<-EOS
1687
+ = Book
1688
+ :doctype: book
1689
+
1690
+ = Part 1
1691
+
1692
+ [partintro]
1693
+ --
1694
+ This is a part intro.
1695
+
1696
+ It can have multiple paragraphs.
1697
+ --
1698
+ EOS
1699
+
1700
+ output = render_string input, :backend => 'docbook'
1701
+ assert_css 'partintro', output, 1
1702
+ assert_css 'part#_part_1 > partintro', output, 1
1703
+ assert_css 'partintro > simpara', output, 2
1704
+ end
1705
+
1706
+ test 'should accept partintro on open block with title rendered to DocBook' do
1707
+ input = <<-EOS
1708
+ = Book
1709
+ :doctype: book
1710
+
1711
+ = Part 1
1712
+
1713
+ .Intro title
1714
+ [partintro]
1715
+ --
1716
+ This is a part intro with a title.
1717
+ --
1718
+ EOS
1719
+
1720
+ output = render_string input, :backend => 'docbook'
1721
+ assert_css 'partintro', output, 1
1722
+ assert_css 'part#_part_1 > partintro', output, 1
1723
+ assert_css 'partintro > title', output, 1
1724
+ assert_css 'partintro > title + simpara', output, 1
1725
+ end
1726
+
1727
+ test 'should exclude partintro if not a child of part rendered to DocBook' do
1728
+ input = <<-EOS
1729
+ = Book
1730
+ :doctype: book
1731
+
1732
+ [partintro]
1733
+ part intro paragraph
1734
+ EOS
1735
+
1736
+ output = render_string input, :backend => 'docbook'
1737
+ assert_css 'partintro', output, 0
1738
+ end
1739
+
1740
+ test 'should not allow partintro unless doctype is book rendered to DocBook' do
1741
+ input = <<-EOS
1742
+ [partintro]
1743
+ part intro paragraph
1744
+ EOS
1745
+
1746
+ output = render_string input, :backend => 'docbook'
1747
+ assert_css 'partintro', output, 0
1748
+ end
1749
+ end
1750
+
1100
1751
  end