summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Allen <dan.j.allen@gmail.com>2013-05-02 02:48:49 -0700
committerDan Allen <dan.j.allen@gmail.com>2013-05-02 02:48:49 -0700
commit6ea2f67913dbd9abc6cb50531212ba053ac8a5c8 (patch)
tree946f936e1256fb15d23b0668a190d37c0a6ee3e3
parentb7ca67ce2615bf414817f5f4f46b53edcd46825b (diff)
parentcac50e5cbeb6219663e865b406605e8ffadd3ca6 (diff)
Merge pull request #305 from mojavelinux/partintro-abstract-support
resolves #297 support for abstract and partintro
-rwxr-xr-xlib/asciidoctor.rb4
-rw-r--r--lib/asciidoctor/abstract_block.rb2
-rw-r--r--lib/asciidoctor/abstract_node.rb28
-rw-r--r--lib/asciidoctor/backends/base_template.rb11
-rw-r--r--lib/asciidoctor/backends/docbook45.rb161
-rw-r--r--lib/asciidoctor/backends/html5.rb79
-rw-r--r--lib/asciidoctor/block.rb4
-rw-r--r--lib/asciidoctor/lexer.rb13
-rw-r--r--test/blocks_test.rb263
-rw-r--r--test/paragraphs_test.rb85
10 files changed, 520 insertions, 130 deletions
diff --git a/lib/asciidoctor.rb b/lib/asciidoctor.rb
index e0f3bfca..e7850272 100755
--- a/lib/asciidoctor.rb
+++ b/lib/asciidoctor.rb
@@ -142,13 +142,13 @@ module Asciidoctor
ADMONITION_STYLES = ['NOTE', 'TIP', 'IMPORTANT', 'WARNING', 'CAUTION'].to_set
# NOTE: AsciiDoc doesn't support pass style for paragraph
- PARAGRAPH_STYLES = ['comment', 'example', 'literal', 'listing', 'normal', 'pass', 'quote', 'sidebar', 'source', 'verse'].to_set
+ PARAGRAPH_STYLES = ['comment', 'example', 'literal', 'listing', 'normal', 'pass', 'quote', 'sidebar', 'source', 'verse', 'abstract', 'partintro'].to_set
VERBATIM_STYLES = ['literal', 'listing', 'source', 'verse'].to_set
DELIMITED_BLOCKS = {
# NOTE: AsciiDoc doesn't support pass style for open block
- '--' => [:open, ['comment', 'example', 'literal', 'listing', 'pass', 'quote', 'sidebar', 'source', 'verse', 'admonition'].to_set],
+ '--' => [:open, ['comment', 'example', 'literal', 'listing', 'pass', 'quote', 'sidebar', 'source', 'verse', 'admonition', 'abstract', 'partintro'].to_set],
'----' => [:listing, ['literal', 'source'].to_set],
'....' => [:literal, ['listing', 'source'].to_set],
'====' => [:example, ['admonition'].to_set],
diff --git a/lib/asciidoctor/abstract_block.rb b/lib/asciidoctor/abstract_block.rb
index 2a6ddd00..2c8d6aa6 100644
--- a/lib/asciidoctor/abstract_block.rb
+++ b/lib/asciidoctor/abstract_block.rb
@@ -63,7 +63,7 @@ class AbstractBlock < AbstractNode
# whether this Block *can* have block content
# that should be the option 'sectionbody'
def blocks?
- !blocks.empty?
+ !@blocks.empty?
end
# Public: Get the element at i in the array of blocks.
diff --git a/lib/asciidoctor/abstract_node.rb b/lib/asciidoctor/abstract_node.rb
index d27c9c73..86356fed 100644
--- a/lib/asciidoctor/abstract_node.rb
+++ b/lib/asciidoctor/abstract_node.rb
@@ -43,14 +43,17 @@ class AbstractNode
# Document node and return the value of the attribute if found. Otherwise,
# return the default value, which defaults to nil.
#
- # name - the name of the attribute to lookup as a String or Symbol
- # default - the value to return if the attribute is not found (default: nil)
+ # name - the String or Symbol name of the attribute to lookup
+ # default - the Object value to return if the attribute is not found (default: nil)
+ # inherit - a Boolean indicating whether to check for the attribute on the
+ # AsciiDoctor::Document if not found on this node (default: false)
#
# return the value of the attribute or the default value if the attribute
# is not found in the attributes of this node or the document node
- def attr(name, default = nil)
+ def attr(name, default = nil, inherit = true)
name = name.to_s if name.is_a?(Symbol)
- if self == @document
+ inherit = false if self == @document
+ if !inherit
default.nil? ? @attributes[name] : @attributes.fetch(name, default)
else
default.nil? ? @attributes.fetch(name, @document.attr(name)) :
@@ -59,26 +62,29 @@ class AbstractNode
end
# Public: Check if the attribute is defined, optionally performing a
- # comparison of its value
+ # comparison of its value if expected is not nil
#
# Check if the attribute is defined. First look in the attributes on this
# node. If not found, and this node is a child of the Document node, look in
# the attributes of the Document node. If the attribute is found and a
- # comparison value is specified, return whether the two values match.
+ # comparison value is specified (not nil), return whether the two values match.
# Otherwise, return whether the attribute was found.
#
- # name - the name of the attribute to lookup as a String or Symbol
- # expect - the expected value of the attribute (default: nil)
+ # name - the String or Symbol name of the attribute to lookup
+ # expect - the expected Object value of the attribute (default: nil)
+ # inherit - a Boolean indicating whether to check for the attribute on the
+ # AsciiDoctor::Document if not found on this node (default: false)
#
# return a Boolean indicating whether the attribute exists and, if a
# comparison value is specified, whether the value of the attribute matches
# the comparison value
- def attr?(name, expect = nil)
+ def attr?(name, expect = nil, inherit = true)
name = name.to_s if name.is_a?(Symbol)
+ inherit = false if self == @document
if expect.nil?
if @attributes.has_key? name
true
- elsif self != @document
+ elsif inherit
@document.attributes.has_key? name
else
false
@@ -86,7 +92,7 @@ class AbstractNode
else
if @attributes.has_key? name
@attributes[name] == expect
- elsif self != @document && @document.attributes.has_key?(name)
+ elsif inherit && @document.attributes.has_key?(name)
@document.attributes[name] == expect
else
false
diff --git a/lib/asciidoctor/backends/base_template.rb b/lib/asciidoctor/backends/base_template.rb
index b8f1a357..da85f027 100644
--- a/lib/asciidoctor/backends/base_template.rb
+++ b/lib/asciidoctor/backends/base_template.rb
@@ -96,10 +96,15 @@ class BaseTemplate
end
# create template matter to insert a style class if the variable has a value
- def attrvalue(key, sibling = true)
+ def attrvalue(key, sibling = true, inherit = true)
delimiter = sibling ? ' ' : ''
- # example: <% if attr? 'foo' %><%= attr 'foo' %><% end %>
- %(<% if attr? '#{key}' %>#{delimiter}<%= attr '#{key}' %><% end %>)
+ if inherit
+ # example: <% if attr? 'foo' %><%= attr 'foo' %><% end %>
+ %(<% if attr? '#{key}' %>#{delimiter}<%= attr '#{key}' %><% end %>)
+ else
+ # example: <% if attr? 'foo', nil, false %><%= attr 'foo', nil, false %><% end %>
+ %(<% if attr? '#{key}', nil, false %>#{delimiter}<%= attr '#{key}', nil, false %><% end %>)
+ end
end
# create template matter to insert an id if one is specified for the block
diff --git a/lib/asciidoctor/backends/docbook45.rb b/lib/asciidoctor/backends/docbook45.rb
index 96348ccc..660977af 100644
--- a/lib/asciidoctor/backends/docbook45.rb
+++ b/lib/asciidoctor/backends/docbook45.rb
@@ -15,9 +15,9 @@ module Asciidoctor
def title_tag(optional = true)
if optional
- %q{<%= title? ? "<title>#{title}</title>" : '' %>}
+ %(<%= title? ? "\n<title>\#{title}</title>" : nil %>)
else
- %q{<title><%= title %></title>}
+ %(\n<title><%= title %></title>)
end
end
@@ -26,7 +26,15 @@ module Asciidoctor
end
def common_attrs_erb
- %q{<%= template.common_attrs(@id, (attr 'role'), (attr 'reftext')) %>}
+ %q(<%= template.common_attrs(@id, (attr 'role'), (attr 'reftext')) %>)
+ end
+
+ def content(node)
+ node.blocks? ? node.content.chomp : "<simpara>#{node.content.chomp}</simpara>"
+ end
+
+ def content_erb
+ %q(<%= blocks? ? content.chomp : "<simpara>#{content.chomp}</simpara>" %>)
end
end
@@ -102,14 +110,14 @@ class DocumentTemplate < BaseTemplate
<bookinfo>
#{docinfo}
</bookinfo>
-<%= content %>
+<%= content.chomp %>
</book>
<% else %>
<article<% unless attr? :nolang %> lang="<%= attr :lang, 'en' %>"<% end %>>
<articleinfo>
#{docinfo}
</articleinfo>
-<%= content %>
+<%= content.chomp %>
</article>
<% end %>
EOF
@@ -135,14 +143,13 @@ end
class BlockPreambleTemplate < BaseTemplate
def template
@template ||= @eruby.new <<-EOF
-<%#encoding:UTF-8%><% if @document.doctype == 'book' %>
-<preface#{common_attrs_erb}>
- #{title_tag false}
-<%= content %>
-</preface>
-<% else %>
-<%= content %>
-<% end %>
+<%#encoding:UTF-8%><%
+if @document.doctype == 'book' %><preface#{common_attrs_erb}>#{title_tag false}
+<%= content.chomp %>
+</preface><%
+else %>
+<%= content.chomp %><%
+end %>
EOF
end
end
@@ -155,9 +162,9 @@ class SectionTemplate < BaseTemplate
tag = sec.document.doctype == 'book' && sec.level <= 1 ? (sec.level == 0 ? 'part' : 'chapter') : 'section'
end
%(<#{tag}#{common_attrs(sec.id, (sec.attr 'role'), (sec.attr 'reftext'))}>
- #{sec.title? ? "<title>#{sec.title}</title>" : nil}
- #{sec.content}
-</#{tag}>)
+#{sec.title? ? "<title>#{sec.title}</title>" : nil}
+#{sec.content.chomp}
+</#{tag}>\n)
end
def template
@@ -175,27 +182,13 @@ end
class BlockParagraphTemplate < BaseTemplate
def paragraph(id, style, role, reftext, title, content)
- # FIXME temporary hack until I can generalize this feature
- if style == 'partintro'
- if title
- %(<partintro#{common_attrs(id, role, reftext)}>
- <title>#{title}</title>
- <simpara>#{content}</simpara>
-</partintro>)
- else
- %(<partintro#{common_attrs(id, role, reftext)}>
- <simpara>#{content}</simpara>
-</partintro>)
- end
+ if !title.nil?
+ %(<formalpara#{common_attrs(id, role, reftext)}>
+<title>#{title}</title>
+<para>#{content}</para>
+</formalpara>\n)
else
- if title
- %(<formalpara#{common_attrs(id, role, reftext)}>
- <title>#{title}</title>
- <para>#{content}</para>
-</formalpara>)
- else
- %(<simpara#{common_attrs(id, role, reftext)}>#{content}</simpara>)
- end
+ %(<simpara#{common_attrs(id, role, reftext)}>#{content}</simpara>\n)
end
end
@@ -211,13 +204,8 @@ end
class BlockAdmonitionTemplate < BaseTemplate
def template
@template ||= @eruby.new <<-EOF
-<%#encoding:UTF-8%><<%= attr :name %>#{common_attrs_erb}>
- #{title_tag}
- <% if blocks? %>
-<%= content %>
- <% else %>
- <simpara><%= content.chomp %></simpara>
- <% end %>
+<%#encoding:UTF-8%><<%= attr :name %>#{common_attrs_erb}>#{title_tag}
+#{content_erb}
</<%= attr :name %>>
EOF
end
@@ -227,8 +215,7 @@ class BlockUlistTemplate < BaseTemplate
def template
@template ||= @eruby.new <<-EOF
<%#encoding:UTF-8%><% if attr? :style, 'bibliography' %>
-<bibliodiv#{common_attrs_erb}>
- #{title_tag}
+<bibliodiv#{common_attrs_erb}>#{title_tag}
<% content.each do |li| %>
<bibliomixed>
<bibliomisc><%= li.text %></bibliomisc>
@@ -239,8 +226,7 @@ class BlockUlistTemplate < BaseTemplate
<% end %>
</bibliodiv>
<% else %>
-<itemizedlist#{common_attrs_erb}>
- #{title_tag}
+<itemizedlist#{common_attrs_erb}>#{title_tag}
<% content.each do |li| %>
<listitem>
<simpara><%= li.text %></simpara>
@@ -258,8 +244,7 @@ end
class BlockOlistTemplate < BaseTemplate
def template
@template ||= @eruby.new <<-EOF
-<%#encoding:UTF-8%><orderedlist#{common_attrs_erb}#{attribute('numeration', :style)}>
- #{title_tag}
+<%#encoding:UTF-8%><orderedlist#{common_attrs_erb}#{attribute('numeration', :style)}>#{title_tag}
<% content.each do |li| %>
<listitem>
<simpara><%= li.text %></simpara>
@@ -276,8 +261,7 @@ end
class BlockColistTemplate < BaseTemplate
def template
@template ||= @eruby.new <<-EOF
-<%#encoding:UTF-8%><calloutlist#{common_attrs_erb}>
- #{title_tag}
+<%#encoding:UTF-8%><calloutlist#{common_attrs_erb}>#{title_tag}
<% content.each do |li| %>
<callout arearefs="<%= li.attr :coids %>">
<para><%= li.text %></para>
@@ -317,8 +301,7 @@ class BlockDlistTemplate < BaseTemplate
def template
@template ||= @eruby.new <<-EOF
<%#encoding:UTF-8%><% tags = (template.class::LIST_TAGS[attr :style] || template.class::LIST_TAGS['labeled']) %>
-<% if tags[:list] %><<%= tags[:list] %>#{common_attrs_erb}><% end %>
- #{title_tag}
+<% if tags[:list] %><<%= tags[:list] %>#{common_attrs_erb}><% end %>#{title_tag}
<% content.each do |dt, dd| %>
<<%= tags[:entry] %>>
<% if tags.has_key?(:label) %>
@@ -350,8 +333,38 @@ class BlockDlistTemplate < BaseTemplate
end
class BlockOpenTemplate < BaseTemplate
+ def result(node)
+ open_block(node, node.id, node.attr('style', nil, false),
+ node.attr('role'), node.attr('reftext'), node.title? ? node.title : nil)
+ end
+
+ def open_block(node, id, style, role, reftext, title)
+ case style
+ when 'abstract'
+ if node.parent == node.document && node.document.attr?('doctype', 'book')
+ puts 'asciidoctor: WARNING: abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
+ ''
+ else
+ %(<abstract>#{title && "\n<title>#{node.title}</title>"}
+#{content node}
+</abstract>\n)
+ end
+ when 'partintro'
+ unless node.document.attr?('doctype', 'book') && node.parent.is_a?(Asciidoctor::Section) && node.level == 0
+ puts 'asciidoctor: ERROR: partintro block can only be used when doctype is book and its a child of a part section. Excluding block content.'
+ ''
+ else
+ %(<partintro#{common_attrs id, role, reftext}>#{title && "\n<title>#{title}</title>"}
+#{content node}
+</partintro>\n)
+ end
+ else
+ node.content
+ end
+ end
+
def template
- :content
+ :invoke_result
end
end
@@ -365,8 +378,7 @@ class BlockListingTemplate < BaseTemplate
<screen#{common_attrs_erb}><%= template.preserve_endlines(content, self) %></screen>
<% end %>
<% else %>
-<formalpara#{common_attrs_erb}>
- #{title_tag false}
+<formalpara#{common_attrs_erb}>#{title_tag false}
<para>
<% if attr :style, 'source' %>
<programlisting language="<%= attr :language %>" linenumbering="<%= (attr? :linenums) ? 'numbered' : 'unnumbered' %>"><%= template.preserve_endlines(content, self) %></programlisting>
@@ -386,8 +398,7 @@ class BlockLiteralTemplate < BaseTemplate
<%#encoding:UTF-8%><% if !title? %>
<literallayout#{common_attrs_erb} class="monospaced"><%= template.preserve_endlines(content, self) %></literallayout>
<% else %>
-<formalpara#{common_attrs_erb}>
- #{title_tag false}
+<formalpara#{common_attrs_erb}>#{title_tag false}
<para>
<literallayout class="monospaced"><%= template.preserve_endlines(content, self) %></literallayout>
</para>
@@ -400,10 +411,9 @@ end
class BlockExampleTemplate < BaseTemplate
def template
@template ||= @eruby.new <<-EOF
-<%#encoding:UTF-8%><example#{common_attrs_erb}>
- #{title_tag}
-<%= content %>
-</example>
+<%#encoding:UTF-8%><<%= (tag_name = title? ? 'example' : 'informalexample') %>#{common_attrs_erb}>#{title_tag}
+#{content_erb}
+</<%= tag_name %>>
EOF
end
end
@@ -411,9 +421,8 @@ end
class BlockSidebarTemplate < BaseTemplate
def template
@template ||= @eruby.new <<-EOF
-<%#encoding:UTF-8%><sidebar#{common_attrs_erb}>
- #{title_tag}
-<%= content %>
+<%#encoding:UTF-8%><sidebar#{common_attrs_erb}>#{title_tag}
+#{content_erb}
</sidebar>
EOF
end
@@ -422,8 +431,7 @@ end
class BlockQuoteTemplate < BaseTemplate
def template
@template ||= @eruby.new <<-EOF
-<%#encoding:UTF-8%><blockquote#{common_attrs_erb}>
- #{title_tag}
+<%#encoding:UTF-8%><blockquote#{common_attrs_erb}>#{title_tag}
<% if (attr? :attribution) || (attr? :citetitle) %>
<attribution>
<% if attr? :attribution %>
@@ -432,11 +440,7 @@ class BlockQuoteTemplate < BaseTemplate
#{tag 'citetitle', :citetitle}
</attribution>
<% end %>
-<% if !@buffer.nil? %>
-<simpara><%= content %></simpara>
-<% else %>
-<%= content %>
-<% end %>
+#{content_erb}
</blockquote>
EOF
end
@@ -445,8 +449,7 @@ end
class BlockVerseTemplate < BaseTemplate
def template
@template ||= @eruby.new <<-EOF
-<%#encoding:UTF-8%><blockquote#{common_attrs_erb}>
- #{title_tag}
+<%#encoding:UTF-8%><blockquote#{common_attrs_erb}>#{title_tag}
<% if (attr? :attribution) || (attr? :citetitle) %>
<attribution>
<% if attr? :attribution %>
@@ -470,9 +473,8 @@ end
class BlockTableTemplate < BaseTemplate
def template
@template ||= @eruby.new <<-EOS
-<%#encoding:UTF-8%><<%= title? ? 'table' : 'informaltable'%>#{common_attrs_erb} frame="<%= attr :frame, 'all'%>"
- rowsep="<%= ['none', 'cols'].include?(attr :grid) ? 0 : 1 %>" colsep="<%= ['none', 'rows'].include?(attr :grid) ? 0 : 1 %>">
- #{title_tag}
+<%#encoding:UTF-8%><<%= (tag_name = title? ? 'table' : 'informaltable') %>#{common_attrs_erb} frame="<%= attr :frame, 'all'%>"
+ rowsep="<%= ['none', 'cols'].include?(attr :grid) ? 0 : 1 %>" colsep="<%= ['none', 'rows'].include?(attr :grid) ? 0 : 1 %>">#{title_tag}
<% if attr? :width %>
<?dbhtml table-width="<%= attr :width %>"?>
<?dbfo table-width="<%= attr :width %>"?>
@@ -505,7 +507,7 @@ class BlockTableTemplate < BaseTemplate
</t<%= tblsec %>>
<% end %>
</tgroup>
-</<%= title? ? 'table' : 'informaltable'%>>
+</<%= tag_name %>>
EOS
end
end
@@ -513,8 +515,7 @@ end
class BlockImageTemplate < BaseTemplate
def template
@template ||= @eruby.new <<-EOF
-<%#encoding:UTF-8%><%#encoding:UTF-8%><figure#{common_attrs_erb}>
- #{title_tag}
+<%#encoding:UTF-8%><%#encoding:UTF-8%><figure#{common_attrs_erb}>#{title_tag}
<mediaobject>
<imageobject>
<imagedata fileref="<%= image_uri(attr :target) %>"#{attribute('contentwidth', :width)}#{attribute('contentdepth', :height)}/>
diff --git a/lib/asciidoctor/backends/html5.rb b/lib/asciidoctor/backends/html5.rb
index 1475561c..4ce43e7f 100644
--- a/lib/asciidoctor/backends/html5.rb
+++ b/lib/asciidoctor/backends/html5.rb
@@ -3,16 +3,20 @@ class BaseTemplate
# create template matter to insert a style class from the role attribute if specified
def role_class
- attrvalue(:role)
+ attrvalue('role')
end
# create template matter to insert a style class from the style attribute if specified
def style_class(sibling = true)
- attrvalue(:style, sibling)
+ attrvalue('style', sibling, false)
end
def title_div(opts = {})
- %(<% if title? %><div class="title">#{opts.has_key?(:caption) ? '<%= @caption %>' : ''}<%= title %></div><% end %>)
+ if opts.has_key? :caption
+ %q(<% if title? %><div class="title"><%= @caption %><%= title %></div><% end %>)
+ else
+ %q(<% if title? %><div class="title"><%= title %></div><% end %>)
+ end
end
end
@@ -184,10 +188,10 @@ class BlockTocTemplate < BaseTemplate
levels = node.attr?('levels') ? node.attr('levels').to_i : doc.attr('toclevels', 2).to_i
role = node.attr?('role') ? node.attr('role') : doc.attr('toc-class', 'toc')
- %(\n<div#{id_attr} class="#{role}">
+ %(<div#{id_attr} class="#{role}">
<div#{title_id_attr} class="title">#{title}</div>
#{DocumentTemplate.outline(doc, levels)}
-</div>)
+</div>\n)
end
def template
@@ -250,7 +254,7 @@ class SectionTemplate < BaseTemplate
%(<div class="sect#{slevel}#{role}">
<#{htag}#{id}>#{sectnum}#{sec.attr 'caption'}#{sec.title}</#{htag}>
#{content}
-</div>)
+</div>\n)
end
end
@@ -271,7 +275,7 @@ class BlockDlistTemplate < BaseTemplate
def template
@template ||= @eruby.new <<-EOS
<%#encoding:UTF-8%><%
-if attr? :style, 'qanda' %>
+if attr? 'style', 'qanda', false %>
<div#{id} class="qlist#{style_class}#{role_class}">
#{title_div}
<ol>
@@ -290,7 +294,7 @@ if attr? :style, 'qanda' %>
<% end %>
</ol>
</div>
-<% elsif attr? :style, 'horizontal' %>
+<% elsif attr? 'style', 'horizontal', false %>
<div#{id} class="hdlist#{role_class}">
#{title_div}
<table>
@@ -317,7 +321,7 @@ if attr? :style, 'qanda' %>
#{title_div}
<dl>
<% content.each do |dt, dd| %>
- <dt<% if !(attr? :style) %> class="hdlist1"<% end %>>
+ <dt<% if !(attr? 'style', nil, false) %> class="hdlist1"<% end %>>
<%= dt.text %>
</dt>
<% unless dd.nil? %>
@@ -344,7 +348,7 @@ class BlockListingTemplate < BaseTemplate
<%#encoding:UTF-8%><div#{id} class="listingblock#{role_class}">
#{title_div :caption => true}
<div class="content monospaced">
- <% if attr? :style, 'source' %>
+ <% if attr? 'style', 'source', false %>
<pre class="highlight<% if attr? 'source-highlighter', 'coderay' %> CodeRay<% end %>"><code#{attribute('class', :language)}><%= template.preserve_endlines(content, self) %></code></pre>
<% else %>
<pre><%= template.preserve_endlines(content, self) %></pre>
@@ -394,10 +398,10 @@ end
class BlockParagraphTemplate < BaseTemplate
def paragraph(id, role, title, content)
- %(<div#{id && " id=\"#{id}\""} class=\"paragraph#{role && " #{role}"}\">#{title && "
- <div class=\"title\">#{title}</div>"}
+ %(<div#{id && " id=\"#{id}\""} class="paragraph#{role && " #{role}"}">#{title && "
+ <div class=\"title\">#{title}</div>"}
<p>#{content}</p>
-</div>)
+</div>\n)
end
def result(node)
@@ -436,15 +440,38 @@ class BlockExampleTemplate < BaseTemplate
end
class BlockOpenTemplate < BaseTemplate
- def template
- @template ||= @eruby.new <<-EOS
-<%#encoding:UTF-8%><div#{id} class="openblock#{role_class}">
- #{title_div}
- <div class="content">
-<%= content %>
- </div>
+ def result(node)
+ open_block(node, node.id, node.attr('style', nil, false), node.attr('role'), node.title? ? node.title : nil, node.content)
+ end
+
+ def open_block(node, id, style, role, title, content)
+ if style == 'abstract'
+ if node.parent == node.document && node.document.attr?('doctype', 'book')
+ puts 'asciidoctor: WARNING: abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
+ ''
+ else
+ %(<div#{id && " id=\"#{id}\""} class="quoteblock abstract#{role && " #{role}"}">#{title &&
+"<div class=\"title\">#{title}</div>"}
+<blockquote>
+#{content}
+</blockquote>
+</div>\n)
+ end
+ elsif style == 'partintro' && (!node.document.attr?('doctype', 'book') || !node.parent.is_a?(Asciidoctor::Section) || node.level != 0)
+ puts 'asciidoctor: ERROR: partintro block can only be used when doctype is book and it\'s a child of a book part. Excluding block content.'
+ ''
+ else
+ %(<div#{id && " id=\"#{id}\""} class="openblock#{style != 'open' ? " #{style}" : ''}#{role && " #{role}"}">#{title &&
+"<div class=\"title\">#{title}</div>"}
+<div class="content">
+#{content}
</div>
- EOS
+</div>\n)
+ end
+ end
+
+ def template
+ :invoke_result
end
end
@@ -519,7 +546,7 @@ class BlockOlistTemplate < BaseTemplate
@template ||= @eruby.new <<-EOS
<%#encoding:UTF-8%><div#{id} class="olist#{style_class}#{role_class}">
#{title_div}
- <ol class="<%= attr :style %>"#{attribute('start', :start)}>
+ <ol class="<%= attr 'style', nil, false %>"#{attribute('start', :start)}>
<% content.each do |item| %>
<li>
<p><%= item.text %></p>
@@ -590,7 +617,7 @@ if attr? :float %>float: <%= attr :float %>; <% end %>">
<% row.each do |cell| %>
<<%= tsec == :head ? 'th' : 'td' %> class="tableblock halign-<%= cell.attr :halign %> valign-<%= cell.attr :valign %>"#{attribute('colspan', 'cell.colspan')}#{attribute('rowspan', 'cell.rowspan')}><%
if tsec == :head %><%= cell.text %><% else %><%
- case cell.attr(:style)
+ case cell.attr('style', nil, false)
when :asciidoc %><div><%= cell.content %></div><%
when :verse %><div class="verse"><%= template.preserve_endlines(cell.text, self) %></div><%
when :literal %><div class="literal monospaced"><pre><%= template.preserve_endlines(cell.text, self) %></pre></div><%
@@ -676,7 +703,7 @@ end
class BlockPageBreakTemplate < BaseTemplate
def result(node)
- '<div style="page-break-after: always;"></div>'
+ %(<div style="page-break-after: always;"></div>\n)
end
def template
@@ -686,7 +713,7 @@ end
class InlineBreakTemplate < BaseTemplate
def result(node)
- "#{node.text}<br>"
+ %(#{node.text}<br>\n)
end
def template
@@ -725,7 +752,7 @@ class InlineQuotedTemplate < BaseTemplate
def quote_text(text, type, role)
start_tag, end_tag = QUOTED_TAGS[type] || NO_TAGS
if role
- "#{start_tag}<span class=\"#{role}\">#{text}</span>#{end_tag}"
+ %(#{start_tag}<span class="#{role}">#{text}</span>#{end_tag})
else
"#{start_tag}#{text}#{end_tag}"
end
diff --git a/lib/asciidoctor/block.rb b/lib/asciidoctor/block.rb
index 9c44d02f..def6d2df 100644
--- a/lib/asciidoctor/block.rb
+++ b/lib/asciidoctor/block.rb
@@ -96,7 +96,7 @@ class Block < AbstractBlock
# => ["<em>This</em> is what happens when you &lt;meet&gt; a stranger in the &lt;alps&gt;!"]
def content
case @context
- when :preamble, :open
+ when :preamble
@blocks.map {|b| b.render }.join
# lists get iterated in the template (for now)
# list items recurse into this block when their text and content methods are called
@@ -106,7 +106,7 @@ class Block < AbstractBlock
apply_literal_subs(@buffer)
when :pass
apply_passthrough_subs(@buffer)
- when :admonition, :example, :sidebar, :quote, :verse
+ when :admonition, :example, :sidebar, :quote, :verse, :open
if !@buffer.nil?
apply_para_subs(@buffer)
else
diff --git a/lib/asciidoctor/lexer.rb b/lib/asciidoctor/lexer.rb
index 65852b70..a7982477 100644
--- a/lib/asciidoctor/lexer.rb
+++ b/lib/asciidoctor/lexer.rb
@@ -211,7 +211,7 @@ class Lexer
end
else
# just take one block or else we run the risk of overrunning section boundaries
- new_block = next_block(reader, section, attributes, :parse_metadata => false)
+ new_block = next_block(reader, (preamble || section), attributes, :parse_metadata => false)
if !new_block.nil?
(preamble || section) << new_block
attributes = {}
@@ -224,8 +224,8 @@ class Lexer
reader.skip_blank_lines
end
- # drop the preamble if it has no content
- if preamble && preamble.blocks.empty?
+ if preamble && !preamble.blocks?
+ # drop the preamble if it has no content
section.delete_at(0)
end
@@ -461,8 +461,7 @@ class Lexer
break
# FIXME create another set for "passthrough" styles
- # though partintro should likely be a dedicated block
- elsif !style.nil? && style != 'normal' && style != 'partintro'
+ elsif !style.nil? && style != 'normal'
if PARAGRAPH_STYLES.include?(style)
block_context = style.to_sym
reader.unshift_line this_line
@@ -565,6 +564,10 @@ class Lexer
# either delimited block or styled paragraph
if block.nil? && !block_context.nil?
+ # abstract and partintro should be handled by open block
+ # FIXME kind of hackish...need to sort out how to generalize this
+ block_context = :open if block_context == :abstract || block_context == :partintro
+
case block_context
when :admonition
attributes['name'] = admonition_name = style.downcase
diff --git a/test/blocks_test.rb b/test/blocks_test.rb
index 2407c8ff..08bba94f 100644
--- a/test/blocks_test.rb
+++ b/test/blocks_test.rb
@@ -1219,4 +1219,267 @@ html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table)
end
end
+ context 'Abstract and Part Intro' do
+ test 'should make abstract on open block without title a quote block for article' do
+ input = <<-EOS
+= Article
+
+[abstract]
+--
+This article is about stuff.
+
+And other stuff.
+--
+ EOS
+
+ output = render_string input
+ assert_css '.quoteblock', output, 1
+ assert_css '.quoteblock.abstract', output, 1
+ assert_css '#preamble .quoteblock', output, 1
+ assert_css '.quoteblock > blockquote', output, 1
+ assert_css '.quoteblock > blockquote > .paragraph', output, 2
+ end
+
+ test 'should make abstract on open block with title a quote block with title for article' do
+ input = <<-EOS
+= Article
+
+.My abstract
+[abstract]
+--
+This article is about stuff.
+--
+ EOS
+
+ output = render_string input
+ assert_css '.quoteblock', output, 1
+ assert_css '.quoteblock.abstract', output, 1
+ assert_css '#preamble .quoteblock', output, 1
+ assert_css '.quoteblock > .title', output, 1
+ assert_css '.quoteblock > .title + blockquote', output, 1
+ assert_css '.quoteblock > .title + blockquote > .paragraph', output, 1
+ end
+
+ test 'should allow abstract in document with title if doctype is book' do
+ input = <<-EOS
+= Book
+:doctype: book
+
+[abstract]
+Abstract for book with title is valid
+ EOS
+
+ output = render_string input
+ assert_css '.abstract', output, 1
+ end
+
+ test 'should not allow abstract as direct child of document if doctype is book' do
+ input = <<-EOS
+:doctype: book
+
+[abstract]
+Abstract for book without title is invalid.
+ EOS
+
+ output = render_string input
+ assert_css '.abstract', output, 0
+ end
+
+ test 'should make abstract on open block without title rendered to DocBook' do
+ input = <<-EOS
+= Article
+
+[abstract]
+--
+This article is about stuff.
+
+And other stuff.
+--
+ EOS
+
+ output = render_string input, :backend => 'docbook'
+ assert_css 'abstract', output, 1
+ assert_css 'abstract > simpara', output, 2
+ end
+
+ test 'should make abstract on open block with title rendered to DocBook' do
+ input = <<-EOS
+= Article
+
+.My abstract
+[abstract]
+--
+This article is about stuff.
+--
+ EOS
+
+ output = render_string input, :backend => 'docbook'
+ assert_css 'abstract', output, 1
+ assert_css 'abstract > title', output, 1
+ assert_css 'abstract > title + simpara', output, 1
+ end
+
+ test 'should allow abstract in document with title if doctype is book rendered to DocBook' do
+ input = <<-EOS
+= Book
+:doctype: book
+
+[abstract]
+Abstract for book with title is valid
+ EOS
+
+ output = render_string input, :backend => 'docbook'
+ assert_css 'abstract', output, 1
+ end
+
+ test 'should not allow abstract as direct child of document if doctype is book rendered to DocBook' do
+ input = <<-EOS
+:doctype: book
+
+[abstract]
+Abstract for book is invalid.
+ EOS
+
+ output = render_string input, :backend => 'docbook'
+ assert_css 'abstract', output, 0
+ end
+
+ # TODO partintro shouldn't be recognized if doctype is not book, should be in proper place
+ test 'should accept partintro on open block without title' do
+ input = <<-EOS
+= Book
+:doctype: book
+
+= Part 1
+
+[partintro]
+--
+This is a part intro.
+
+It can have multiple paragraphs.
+--
+ EOS
+
+ output = render_string input
+ assert_css '.openblock', output, 1
+ assert_css '.openblock.partintro', output, 1
+ assert_css '.openblock .title', output, 0
+ assert_css '.openblock .content', output, 1
+ assert_xpath %(//h1[@id="_part_1"]/following-sibling::*[#{contains_class(:openblock)}]), output, 1
+ assert_xpath %(//*[#{contains_class(:openblock)}]/*[@class="content"]/*[@class="paragraph"]), output, 2
+ end
+
+ test 'should accept partintro on open block with title' do
+ input = <<-EOS
+= Book
+:doctype: book
+
+= Part 1
+
+.Intro title
+[partintro]
+--
+This is a part intro with a title.
+--
+ EOS
+
+ output = render_string input
+ assert_css '.openblock', output, 1
+ assert_css '.openblock.partintro', output, 1
+ assert_css '.openblock .title', output, 1
+ assert_css '.openblock .content', output, 1
+ assert_xpath %(//h1[@id="_part_1"]/following-sibling::*[#{contains_class(:openblock)}]), output, 1
+ assert_xpath %(//*[#{contains_class(:openblock)}]/*[@class="title"][text() = "Intro title"]), output, 1
+ assert_xpath %(//*[#{contains_class(:openblock)}]/*[@class="content"]/*[@class="paragraph"]), output, 1
+ end
+
+ test 'should exclude partintro if not a child of part' do
+ input = <<-EOS
+= Book
+:doctype: book
+
+[partintro]
+part intro paragraph
+ EOS
+
+ output = render_string input
+ assert_css '.partintro', output, 0
+ end
+
+ test 'should not allow partintro unless doctype is book' do
+ input = <<-EOS
+[partintro]
+part intro paragraph
+ EOS
+
+ output = render_string input
+ assert_css '.partintro', output, 0
+ end
+
+ test 'should accept partintro on open block without title rendered to DocBook' do
+ input = <<-EOS
+= Book
+:doctype: book
+
+= Part 1
+
+[partintro]
+--
+This is a part intro.
+
+It can have multiple paragraphs.
+--
+ EOS
+
+ output = render_string input, :backend => 'docbook'
+ assert_css 'partintro', output, 1
+ assert_css 'part#_part_1 > partintro', output, 1
+ assert_css 'partintro > simpara', output, 2
+ end
+
+ test 'should accept partintro on open block with title rendered to DocBook' do
+ input = <<-EOS
+= Book
+:doctype: book
+
+= Part 1
+
+.Intro title
+[partintro]
+--
+This is a part intro with a title.
+--
+ EOS
+
+ output = render_string input, :backend => 'docbook'
+ assert_css 'partintro', output, 1
+ assert_css 'part#_part_1 > partintro', output, 1
+ assert_css 'partintro > title', output, 1
+ assert_css 'partintro > title + simpara', output, 1
+ end
+
+ test 'should exclude partintro if not a child of part rendered to DocBook' do
+ input = <<-EOS
+= Book
+:doctype: book
+
+[partintro]
+part intro paragraph
+ EOS
+
+ output = render_string input, :backend => 'docbook'
+ assert_css 'partintro', output, 0
+ end
+
+ test 'should not allow partintro unless doctype is book rendered to DocBook' do
+ input = <<-EOS
+[partintro]
+part intro paragraph
+ EOS
+
+ output = render_string input, :backend => 'docbook'
+ assert_css 'partintro', output, 0
+ end
+ end
+
end
diff --git a/test/paragraphs_test.rb b/test/paragraphs_test.rb
index 1de9bf68..74d4a759 100644
--- a/test/paragraphs_test.rb
+++ b/test/paragraphs_test.rb
@@ -366,5 +366,90 @@ Content goes here
result = render_string(input)
assert_xpath "//*[@class='sidebarblock']//p", result, 1
end
+
+ context 'Styled Paragraphs' do
+ test 'should wrap text in simpara for styled paragraphs when rendered to DocBook' do
+ input = <<-EOS
+= Book
+:doctype: book
+
+[preface]
+= About this book
+
+[abstract]
+An abstract for the book.
+
+= Part 1
+
+[partintro]
+An intro to this part.
+
+[sidebar]
+Just a side note.
+
+[example]
+As you can see here.
+
+[quote]
+Wise words from a wise person.
+ EOS
+
+ output = render_string input, :backend => 'docbook'
+ assert_css 'abstract > simpara', output, 1
+ assert_css 'partintro > simpara', output, 1
+ assert_css 'sidebar > simpara', output, 1
+ assert_css 'informalexample > simpara', output, 1
+ assert_css 'blockquote > simpara', output, 1
+ end
+
+ test 'wip should wrap text in simpara for styled paragraphs with title when rendered to DocBook' do
+ input = <<-EOS
+= Book
+:doctype: book
+
+[preface]
+= About this book
+
+[abstract]
+.Abstract title
+An abstract for the book.
+
+= Part 1
+
+[partintro]
+.Part intro title
+An intro to this part.
+
+[sidebar]
+.Sidebar title
+Just a side note.
+
+[example]
+.Example title
+As you can see here.
+
+[quote]
+.Quote title
+Wise words from a wise person.
+ EOS
+
+ output = render_string input, :backend => 'docbook'
+ assert_css 'abstract > title', output, 1
+ assert_xpath '//abstract/title[text() = "Abstract title"]', output, 1
+ assert_css 'abstract > title + simpara', output, 1
+ assert_css 'partintro > title', output, 1
+ assert_xpath '//partintro/title[text() = "Part intro title"]', output, 1
+ assert_css 'partintro > title + simpara', output, 1
+ assert_css 'sidebar > title', output, 1
+ assert_xpath '//sidebar/title[text() = "Sidebar title"]', output, 1
+ assert_css 'sidebar > title + simpara', output, 1
+ assert_css 'example > title', output, 1
+ assert_xpath '//example/title[text() = "Example title"]', output, 1
+ assert_css 'example > title + simpara', output, 1
+ assert_css 'blockquote > title', output, 1
+ assert_xpath '//blockquote/title[text() = "Quote title"]', output, 1
+ assert_css 'blockquote > title + simpara', output, 1
+ end
+ end
end
end