diff options
| author | Dan Allen <dan.j.allen@gmail.com> | 2013-05-02 02:48:49 -0700 |
|---|---|---|
| committer | Dan Allen <dan.j.allen@gmail.com> | 2013-05-02 02:48:49 -0700 |
| commit | 6ea2f67913dbd9abc6cb50531212ba053ac8a5c8 (patch) | |
| tree | 946f936e1256fb15d23b0668a190d37c0a6ee3e3 | |
| parent | b7ca67ce2615bf414817f5f4f46b53edcd46825b (diff) | |
| parent | cac50e5cbeb6219663e865b406605e8ffadd3ca6 (diff) | |
Merge pull request #305 from mojavelinux/partintro-abstract-support
resolves #297 support for abstract and partintro
| -rwxr-xr-x | lib/asciidoctor.rb | 4 | ||||
| -rw-r--r-- | lib/asciidoctor/abstract_block.rb | 2 | ||||
| -rw-r--r-- | lib/asciidoctor/abstract_node.rb | 28 | ||||
| -rw-r--r-- | lib/asciidoctor/backends/base_template.rb | 11 | ||||
| -rw-r--r-- | lib/asciidoctor/backends/docbook45.rb | 161 | ||||
| -rw-r--r-- | lib/asciidoctor/backends/html5.rb | 79 | ||||
| -rw-r--r-- | lib/asciidoctor/block.rb | 4 | ||||
| -rw-r--r-- | lib/asciidoctor/lexer.rb | 13 | ||||
| -rw-r--r-- | test/blocks_test.rb | 263 | ||||
| -rw-r--r-- | test/paragraphs_test.rb | 85 |
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 <meet> a stranger in the <alps>!"] 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 |
