# encoding: UTF-8 require_relative 'spine_item_processor' require_relative 'font_icon_map' module Asciidoctor module Epub3 # tried 8288, but it didn't work in older readers WordJoiner = [65279].pack 'U*' WordJoinerRx = RUBY_ENGINE_JRUBY ? /uFEFF/ : WordJoiner # Public: The main converter for the epub3 backend that handles packaging the # EPUB3 or KF8 publication file. class Converter include ::Asciidoctor::Converter include ::Asciidoctor::Writer register_for 'epub3' def initialize backend, opts super basebackend 'html' outfilesuffix '.epub' # dummy outfilesuffix since it may be .mobi htmlsyntax 'xml' @validate = false @extract = false end def convert spine_doc, name = nil @validate = true if spine_doc.attr? 'ebook-validate' @extract = true if spine_doc.attr? 'ebook-extract' Packager.new spine_doc, (spine_doc.references[:spine_items] || [spine_doc]), spine_doc.attributes['ebook-format'].to_sym end # FIXME we have to package in write because we don't have access to target before this point def write packager, target # NOTE we use dirname of target since filename is calculated automatically packager.package validate: @validate, extract: @extract, to_dir: (::File.dirname target) nil end end # Public: The converter for the epub3 backend that converts the individual # content documents in an EPUB3 publication. class ContentConverter include ::Asciidoctor::Converter register_for 'epub3-xhtml5' WordJoiner = Epub3::WordJoiner EOL = "\n" NoBreakSpace = ' ' ThinNoBreakSpace = ' ' RightAngleQuote = '›' XmlElementRx = /<\/?.+?>/ CharEntityRx = /(\d{2,5});/ NamedEntityRx = /&([A-Z]+);/ UppercaseTagRx = /<(\/)?([A-Z]+)>/ FromHtmlSpecialCharsMap = { '<' => '<', '>' => '>', '&' => '&' } FromHtmlSpecialCharsRx = /(?:#{FromHtmlSpecialCharsMap.keys * '|'})/ ToHtmlSpecialCharsMap = { '&' => '&', '<' => '<', '>' => '>' } ToHtmlSpecialCharsRx = /[#{ToHtmlSpecialCharsMap.keys.join}]/ OpenParagraphTagRx = /^
/ CloseParagraphTagRx = /<\/p>$/ def initialize backend, opts super basebackend 'html' outfilesuffix '.xhtml' htmlsyntax 'xml' @xrefs_used = ::Set.new @icon_names = [] end def convert node, name = nil if respond_to?(name ||= node.node_name) send name, node else warn %(conversion missing in epub3 backend for #{name}) end end # TODO aggregate authors of spine document into authors attribute(s) on main document def navigation_document node, spine doctitle_sanitized = (node.doctitle sanitize: true, use_fallback: true).gsub WordJoinerRx, '' lines = [%(