lib/asciidoctor-epub3/converter.rb in asciidoctor-epub3-1.5.0.alpha.11 vs lib/asciidoctor-epub3/converter.rb in asciidoctor-epub3-1.5.0.alpha.12
- old
+ new
@@ -19,17 +19,21 @@
basebackend 'html'
outfilesuffix '.epub' # dummy outfilesuffix since it may be .mobi
htmlsyntax 'xml'
@validate = false
@extract = false
+ @kindlegen_path = nil
+ @epubcheck_path = nil
end
def convert node, name = nil
if (name ||= node.node_name) == 'document'
@validate = node.attr? 'ebook-validate'
@extract = node.attr? 'ebook-extract'
@compress = node.attr 'ebook-compress'
+ @kindlegen_path = node.attr 'ebook-kindlegen-path'
+ @epubcheck_path = node.attr 'ebook-epubcheck-path'
spine_items = node.references[:spine_items]
if spine_items.nil?
logger.error %(#{::File.basename node.document.attr('docfile')}: failed to find spine items, produced file will be invalid)
spine_items = []
end
@@ -42,11 +46,11 @@
end
end
# FIXME: we have to package in write because we don't have access to target before this point
def write packager, target
- packager.package validate: @validate, extract: @extract, compress: @compress, target: target
+ packager.package validate: @validate, extract: @extract, compress: @compress, kindlegen_path: @kindlegen_path, epubcheck_path: @epubcheck_path, target: target
nil
end
end
# Public: The converter for the epub3 backend that converts the individual
@@ -90,19 +94,20 @@
htmlsyntax 'xml'
@xrefs_seen = ::Set.new
@icon_names = []
end
- def convert node, name = nil
- if respond_to? name ||= node.node_name
- send name, node
+ def convert node, name = nil, _opts = {}
+ method_name = %(convert_#{name ||= node.node_name})
+ if respond_to? method_name
+ send method_name, node
else
- logger.warn %(conversion missing in epub3 backend for #{name})
+ logger.warn %(conversion missing in backend #{@backend} for #{name})
end
end
- def document node
+ def convert_document node
docid = node.id
pubtype = node.attr 'publication-type', 'book'
if (doctitle = node.doctitle partition: true, use_fallback: true).subtitle?
title = %(#{doctitle.main} )
@@ -191,15 +196,15 @@
lines * LF
end
# NOTE embedded is used for AsciiDoc table cell content
- def embedded node
+ def convert_embedded node
node.content
end
- def section node
+ def convert_section node
hlevel = node.level + 1
epub_type_attr = node.special ? %( epub:type="#{node.sectname}") : ''
div_classes = [%(sect#{node.level}), node.role].compact
title = node.title
title_sanitized = xml_sanitize title
@@ -213,40 +218,40 @@
node.content
end
end
# TODO: support use of quote block as abstract
- def preamble node
+ def convert_preamble node
if (first_block = node.blocks[0]) && first_block.style == 'abstract'
- abstract first_block
+ convert_abstract first_block
# REVIEW: should we treat the preamble as an abstract in general?
elsif first_block && node.blocks.size == 1
- abstract first_block
+ convert_abstract first_block
else
node.content
end
end
- def open node
+ def convert_open node
id_attr = node.id ? %( id="#{node.id}") : nil
class_attr = node.role ? %( class="#{node.role}") : nil
if id_attr || class_attr
%(<div#{id_attr}#{class_attr}>
-#{convert_content node}
+#{output_content node}
</div>)
else
- convert_content node
+ output_content node
end
end
- def abstract node
+ def convert_abstract node
%(<div class="abstract" epub:type="preamble">
-#{convert_content node}
+#{output_content node}
</div>)
end
- def paragraph node
+ def convert_paragraph node
role = node.role
# stack-head is the alternative to the default, inline-head (where inline means "run-in")
head_stop = node.attr 'head-stop', (role && (node.has_role? 'stack-head') ? nil : '.')
head = node.title? ? %(<strong class="head">#{title = node.title}#{head_stop && title !~ TrailingPunctRx ? head_stop : ''}</strong> ) : ''
if role
@@ -255,20 +260,20 @@
else
%(<p>#{head}#{node.content}</p>)
end
end
- def pass node
+ def convert_pass node
content = node.content
if content == '<?hard-pagebreak?>'
'<hr epub:type="pagebreak" class="pagebreak"/>'
else
content
end
end
- def admonition node
+ def convert_admonition node
id_attr = node.id ? %( id="#{node.id}") : ''
if node.title?
title = node.title
title_sanitized = xml_sanitize title
title_attr = %( title="#{node.caption}: #{title_sanitized}")
@@ -288,33 +293,33 @@
when 'important', 'warning', 'caution'
'warning'
end
%(<aside#{id_attr} class="admonition #{type}"#{title_attr} epub:type="#{epub_type}">
#{title_el}<div class="content">
-#{convert_content node}
+#{output_content node}
</div>
</aside>)
end
- def example node
+ def convert_example node
id_attr = node.id ? %( id="#{node.id}") : ''
title_div = node.title? ? %(<div class="example-title">#{node.title}</div>
) : ''
%(<div#{id_attr} class="example">
#{title_div}<div class="example-content">
-#{convert_content node}
+#{output_content node}
</div>
</div>)
end
- def floating_title node
+ def convert_floating_title node
tag_name = %(h#{node.level + 1})
id_attribute = node.id ? %( id="#{node.id}") : ''
%(<#{tag_name}#{id_attribute} class="#{['discrete', node.role].compact * ' '}">#{node.title}</#{tag_name}>)
end
- def listing node
+ def convert_listing node
figure_classes = ['listing']
figure_classes << 'coalesce' if node.option? 'unbreakable'
pre_classes = node.style == 'source' ? ['source', %(language-#{node.attr 'language'})] : ['screen']
title_div = node.title? ? %(<figcaption>#{node.captioned_title}</figcaption>
) : ''
@@ -324,23 +329,23 @@
#{title_div}<pre class="#{pre_classes * ' '}"><code>#{(node.content || '').gsub(/(?<! )<i class="conum"| +<i class="conum"/, ' <i class="conum"')}</code></pre>
</figure>)
end
# QUESTION should we wrap the <pre> in either <div> or <figure>?
- def literal node
+ def convert_literal node
%(<pre class="screen">#{node.content}</pre>)
end
- def page_break _node
+ def convert_page_break _node
'<hr epub:type="pagebreak" class="pagebreak"/>'
end
- def thematic_break _node
+ def convert_thematic_break _node
'<hr class="thematicbreak"/>'
end
- def quote node
+ def convert_quote node
id_attr = %( id="#{node.id}") if node.id
class_attr = (role = node.role) ? %( class="blockquote #{role}") : ' class="blockquote"'
footer_content = []
if (attribution = node.attr 'attribution')
@@ -354,19 +359,19 @@
footer_content << %(<span class="context">#{node.title}</span>) if node.title?
footer_tag = footer_content.empty? ? '' : %(
<footer>~ #{footer_content * ' '}</footer>)
- content = (convert_content node).strip
+ content = (output_content node).strip
%(<div#{id_attr}#{class_attr}>
<blockquote>
#{content}#{footer_tag}
</blockquote>
</div>)
end
- def verse node
+ def convert_verse node
id_attr = %( id="#{node.id}") if node.id
class_attr = (role = node.role) ? %( class="verse #{role}") : ' class="verse"'
footer_content = []
if (attribution = node.attr 'attribution')
@@ -383,11 +388,11 @@
%(<div#{id_attr}#{class_attr}>
<pre>#{node.content}#{footer_tag}</pre>
</div>)
end
- def sidebar node
+ def convert_sidebar node
classes = ['sidebar']
if node.title?
classes << 'titled'
title = node.title
title_sanitized = xml_sanitize title
@@ -398,16 +403,16 @@
title_attr = title_el = ''
end
%(<aside class="#{classes * ' '}"#{title_attr} epub:type="sidebar">
#{title_el}<div class="content">
-#{convert_content node}
+#{output_content node}
</div>
</aside>)
end
- def table node
+ def convert_table node
lines = [%(<div class="table">)]
lines << %(<div class="content">)
table_id_attr = node.id ? %( id="#{node.id}") : ''
frame_class = {
'all' => 'table-framed',
@@ -491,11 +496,11 @@
</div>
</div>'
lines * LF
end
- def colist node
+ def convert_colist node
lines = ['<div class="callout-list">
<ol>']
num = CalloutStartNum
node.items.each_with_index do |item, i|
lines << %(<li><i class="conum" data-value="#{i + 1}">#{num}</i> #{item.text}</li>)
@@ -504,11 +509,11 @@
lines << '</ol>
</div>'
end
# TODO: add complex class if list has nested blocks
- def dlist node
+ def convert_dlist node
lines = []
case (style = node.style)
when 'itemized', 'ordered'
list_tag_name = style == 'itemized' ? 'ul' : 'ol'
role = node.role
@@ -558,11 +563,11 @@
</div>'
end
lines * LF
end
- def olist node
+ def convert_olist node
complex = false
div_classes = ['ordered-list', node.style, node.role].compact
ol_classes = [node.style, ((node.option? 'brief') ? 'brief' : nil)].compact
ol_class_attr = ol_classes.empty? ? '' : %( class="#{ol_classes * ' '}")
ol_start_attr = (node.attr? 'start') ? %( start="#{node.attr 'start'}") : ''
@@ -586,11 +591,11 @@
lines << '</ol>
</div>'
lines * LF
end
- def ulist node
+ def convert_ulist node
complex = false
div_classes = ['itemized-list', node.style, node.role].compact
ul_classes = [node.style, ((node.option? 'brief') ? 'brief' : nil)].compact
ul_class_attr = ul_classes.empty? ? '' : %( class="#{ul_classes * ' '}")
id_attribute = node.id ? %( id="#{node.id}") : ''
@@ -613,11 +618,11 @@
lines << '</ul>
</div>'
lines * LF
end
- def image node
+ def convert_image node
target = node.attr 'target'
type = (::File.extname target)[1..-1]
id_attr = node.id ? %( id="#{node.id}") : ''
img_attrs = [%(alt="#{node.attr 'alt'}")]
case type
@@ -652,11 +657,11 @@
</div>#{node.title? ? %(
<figcaption>#{node.captioned_title}</figcaption>) : ''}
</figure>)
end
- def inline_anchor node
+ def convert_inline_anchor node
target = node.target
case node.type
when :xref # TODO: would be helpful to know what type the target is (e.g., bibref)
doc, refid, text, path = node.document, ((node.attr 'refid') || target), node.text, (node.attr 'path')
# NOTE if path is non-nil, we have an inter-document xref
@@ -720,34 +725,34 @@
%(<a id="#{target}"></a>[#{target}])
end
end
end
- def inline_break node
+ def convert_inline_break node
%(#{node.text}<br/>)
end
- def inline_button node
+ def convert_inline_button node
%(<b class="button">[<span class="label">#{node.text}</span>]</b>)
end
- def inline_callout node
+ def convert_inline_callout node
num = CalloutStartNum
int_num = node.text.to_i
(int_num - 1).times { num = num.next }
%(<i class="conum" data-value="#{int_num}">#{num}</i>)
end
- def inline_footnote node
+ def convert_inline_footnote node
if (index = node.attr 'index')
%(<sup class="noteref">[<a id="noteref-#{index}" href="#note-#{index}" epub:type="noteref">#{index}</a>]</sup>)
elsif node.type == :xref
%(<mark class="noteref" title="Unresolved note reference">#{node.text}</mark>)
end
end
- def inline_image node
+ def convert_inline_image node
if node.type == 'icon'
@icon_names << (icon_name = node.target)
i_classes = ['icon', %(i-#{icon_name})]
i_classes << %(icon-#{node.attr 'size'}) if node.attr? 'size'
i_classes << %(icon-flip-#{(node.attr 'flip')[0]}) if node.attr? 'flip'
@@ -767,24 +772,24 @@
end
%(<img src="#{target}" #{img_attrs * ' '}/>)
end
end
- def inline_indexterm node
+ def convert_inline_indexterm node
node.type == :visible ? node.text : ''
end
- def inline_kbd node
+ def convert_inline_kbd node
if (keys = node.attr 'keys').size == 1
%(<kbd>#{keys[0]}</kbd>)
else
key_combo = keys.map {|key| %(<kbd>#{key}</kbd>) }.join '+'
%(<span class="keyseq">#{key_combo}</span>)
end
end
- def inline_menu node
+ def convert_inline_menu node
menu = node.attr 'menu'
# NOTE we swap right angle quote with chevron right from FontAwesome using CSS
caret = %(#{NoBreakSpace}<span class="caret">#{RightAngleQuote}</span> )
if !(submenus = node.attr 'submenus').empty?
submenu_path = submenus.map {|submenu| %(<span class="submenu">#{submenu}</span>#{caret}) }.join.chop
@@ -794,11 +799,11 @@
else
%(<span class="menu">#{menu}</span>)
end
end
- def inline_quoted node
+ def convert_inline_quoted node
case node.type
when :strong
%(<strong>#{node.text}</strong>)
when :emphasis
%(<em>#{node.text}</em>)
@@ -817,11 +822,11 @@
else
node.text
end
end
- def convert_content node
+ def output_content node
node.content_model == :simple ? %(<p>#{node.content}</p>) : node.content
end
# FIXME: merge into with xml_sanitize helper
def xml_sanitize value, target = :attribute
@@ -913,10 +918,11 @@
Extensions.register do
if (document = @document).backend == 'epub3'
document.attributes['spine'] = ''
document.set_attribute 'listing-caption', 'Listing'
- if !(defined? ::JRuby) && (::Gem.try_activate 'pygments.rb')
+ # pygments.rb hangs on JRuby for Windows, see https://github.com/asciidoctor/asciidoctor-epub3/issues/253
+ if !(::RUBY_ENGINE == 'jruby' && Gem.win_platform?) && (Gem.try_activate 'pygments.rb')
if document.set_attribute 'source-highlighter', 'pygments'
document.set_attribute 'pygments-css', 'style'
document.set_attribute 'pygments-style', 'bw'
end
end