# frozen_string_literal: true
require 'asciidoctor'
require 'asciidoctor/converter'
require 'fb2rb'
module Asciidoctor
module FB2
# Converts AsciiDoc documents to FB2 e-book formats
class Converter < Asciidoctor::Converter::Base # rubocop:disable Metrics/ClassLength
include ::Asciidoctor::Writer
CSV_DELIMITER_REGEX = /\s*,\s*/.freeze
register_for 'fb2'
# @return [FB2rb::Book]
attr_reader(:book)
def initialize(backend, opts = {})
super
outfilesuffix '.fb2.zip'
end
# @param node [Asciidoctor::Document]
def convert_document(node) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
@book = FB2rb::Book.new
document_info = @book.description.document_info
title_info = @book.description.title_info
title_info.book_title = node.doctitle
title_info.lang = node.attr('lang', 'en')
(node.attr 'keywords', '').split(CSV_DELIMITER_REGEX).each do |s|
title_info.keywords << s
end
(node.attr 'genres', '').split(CSV_DELIMITER_REGEX).each do |s|
title_info.genres << s
end
node.authors.each do |author|
title_info.authors << FB2rb::Author.new(
author.firstname,
author.middlename,
author.lastname,
nil,
[],
author.email.nil? ? [] : [author.email]
)
end
if node.attr? 'series-name'
series_name = node.attr 'series-name'
series_volume = node.attr 'series-volume', 1
title_info.sequences << FB2rb::Sequence.new(series_name, series_volume)
end
date = node.attr('revdate') || node.attr('docdate')
fb2date = FB2rb::FB2Date.new(date, Date.parse(date))
title_info.date = document_info.date = fb2date
document_info.id = node.attr('uuid', '')
document_info.version = node.attr('revnumber')
document_info.program_used = %(Asciidoctor FB2 #{VERSION} using Asciidoctor #{node.attr('asciidoctor-version')})
publisher = node.attr('publisher')
document_info.publishers << publisher if publisher
body = %( #{node.doctitle} #{footnote.index} #{footnote.text} #{node.title}
', node.content, '
' ] lines << '#{line}
', '
'],
emphasis: ['', '
'],
latexmath: ['', '
']
}).default = ['', '']
# @param node [Asciidoctor::Inline]
def convert_inline_quoted(node)
open, close = QUOTE_TAGS[node.type]
%(#{open}#{node.text}#{close})
end
# @param node [Asciidoctor::Inline]
def convert_inline_anchor(node) # rubocop:disable Metrics/MethodLength
case node.type
when :xref
%(#{node.text})
when :link
%(#{node.text})
when :ref
%()
when :bibref
unless (reftext = node.reftext)
reftext = %([#{node.id}])
end
%(#{reftext})
else
logger.warn %(unknown anchor type: #{node.type.inspect})
nil
end
end
# @param node [Asciidoctor::Inline]
def convert_inline_footnote(node)
index = node.attr('index')
%([#{index}])
end
# @param node [Asciidoctor::Inline]
def convert_inline_image(node)
image_attrs = resolve_image_attrs(node, node.target)
%(#{node.title || node.caption}: #{node.content}
) end # @param node [Asciidoctor::List] def convert_ulist(node) lines = [] node.items.each do |item| lines << %(• #{item.text}
) lines << %(#{item.content}
) if item.blocks? end lines << '#{index + 1}. #{item.text}
) lines << %(#{item.content}
) if item.blocks? end lines << ''
first_term = true
terms.each do |dt|
lines << %( ' lines << '' if node.option?('strong') lines << dt.text lines << '' if node.option?('strong') lines << ' ' first_term = false end lines << ' | '
lines << ''
if dd
lines << %( #{dd.text} ) if dd.text? lines << dd.content if dd.blocks? end lines << ' | '
lines << '