Class: EPUB::Maker::Task

Inherits:
Rake::TaskLib
  • Object
show all
Defined in:
lib/epub/maker/task.rb

Constant Summary collapse

DUMMY_ROOT_IRI =
Addressable::URI.parse('dummy:///').freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) {|_self| ... } ⇒ Task

Returns a new instance of Task.

Parameters:

  • name (String)

    EPUB file name

Yields:

  • (_self)

Yield Parameters:



19
20
21
22
23
# File 'lib/epub/maker/task.rb', line 19

def initialize(name)
  init name
  yield self if block_given?
  define
end

Instance Attribute Details

#base_dirObject

Returns the value of attribute base_dir.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def base_dir
  @base_dir
end

#bindingsObject

Returns the value of attribute bindings.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def bindings
  @bindings
end

#containerObject

Returns the value of attribute container.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def container
  @container
end

#contributorsObject

Returns the value of attribute contributors.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def contributors
  @contributors
end

#cover_imageObject

Returns the value of attribute cover_image.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def cover_image
  @cover_image
end

#file_map_procObject

Returns the value of attribute file_map_proc.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def file_map_proc
  @file_map_proc
end

#filesObject

Returns the value of attribute files.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def files
  @files
end

#languageObject

Returns the value of attribute language.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def language
  @language
end

#make_rootfilesObject

Returns the value of attribute make_rootfiles.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def make_rootfiles
  @make_rootfiles
end

#media_typesObject

Returns the value of attribute media_types.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def media_types
  @media_types
end

Returns the value of attribute navs.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def navs
  @navs
end

#package_directionObject

Returns the value of attribute package_direction.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def package_direction
  @package_direction
end

#resourcesObject

Returns the value of attribute resources.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def resources
  @resources
end

#rootfilesObject

Returns the value of attribute rootfiles.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def rootfiles
  @rootfiles
end

#spineObject

Returns the value of attribute spine.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def spine
  @spine
end

#targetObject

Returns the value of attribute target.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def target
  @target
end

#titlesObject

Returns the value of attribute titles.



11
12
13
# File 'lib/epub/maker/task.rb', line 11

def titles
  @titles
end

Instance Method Details

#defineObject



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/epub/maker/task.rb', line 43

def define
  desc 'Make EPUB file'
  task @target do
    EPUB::Maker.make @name do |book|
      book.make_ocf do |ocf|
        if container
          ocf.container = EPUB::Parser::OCF.new(nil).parse_container(File.read(container))
        else
          raise 'Set at least one rootfile' if rootfiles.empty?
          ocf.make_container do |container|
            rootfiles.each do |rootfile|
              container.make_rootfile full_path: Addressable::URI.parse(file_map[rootfile])
            end
          end
        end
      end

      if make_rootfiles
        book.make_package do |package|
          book.ocf.container.rootfile.package = package

          package.dir = package_direction

          package. do ||
            .title = @titles.first
            .language = language
          end

          package.make_manifest do |manifest|
            rootfile_absolute_path = DUMMY_ROOT_IRI + package.book.ocf.container.rootfile.full_path
            resources.each_with_index do |resource, index|
              resource_absolute_iri = DUMMY_ROOT_IRI + file_map[resource]
              manifest.make_item do |item|
                item.id = "item-#{index + 1}"
                item.href = resource_absolute_iri.route_from(rootfile_absolute_path)
                item.media_type = detect_media_type(resource)
                item.content_file = resource
                item.properties << 'nav' if navs.include? item.entry_name
                item.properties << 'scripted' unless Nokogiri.XML(open(resource)).search('script').empty?
              end
            end
          end

          package.make_spine do |spine|
            @spine.each do |item_path|
              entry_name = file_map[item_path]
              spine.make_itemref do |itemref|
                item = package.manifest.items.find {|i| i.entry_name == entry_name}
                itemref.item = item if item
                warn "missing item #{item_path}, referred by itemref" if itemref.item.nil?
                itemref.linear = true # TODO: Make more customizable
              end
            end
          end

          if @bindings and !@bindings.empty?
            package.make_bindings do |bindings|
              @bindings.each_pair do |media_type, handler_path|
                bindings.make_media_type do |mt|
                  mt.media_type = media_type
                  entry_name = file_map[handler_path]
                  mt.handler = package.manifest.items.find {|item| item.entry_name == entry_name}
                  warn "missing handler for #{media_type}" if mt.handler.nil?
                end
              end
            end
          end
        end
      else
        raise 'No rootfile set' if rootfiles.empty?
        rf = rootfiles.first
        package = EPUB::Parser::Publication.new(File.read(rf)).parse
        book.rootfiles.first.package = package
        package.book = book
      end
    end
  end
end

#detect_media_type(resource) ⇒ String

Returns detected media type.

Parameters:

  • resource (String)

    resource path to detect media type

Returns:

  • (String)

    detected media type



139
140
141
142
143
144
145
146
147
148
# File 'lib/epub/maker/task.rb', line 139

def detect_media_type(resource)
  detected = media_types[resource]
  return detected if detected

  detected = MimeMagic.by_magic(open(resource)).type
  detected = 'application/xhtml+xml' if detected == 'text/html'
  return detected if detected

  MimeMagic.by_path(resource).type
end

#file_map(force_calculation = false) ⇒ Object



127
128
129
130
131
132
133
134
135
# File 'lib/epub/maker/task.rb', line 127

def file_map(force_calculation=false)
  if force_calculation or @file_map.empty?
    @file_map.clear
    @files.each do |src_name|
      @file_map[src_name] = @file_map_proc[src_name]
    end
  end
  @file_map
end

#init(name) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/epub/maker/task.rb', line 25

def init(name)
  @target = :epub
  @name = name
  @files = FileList.new
  @base_dir = Dir.pwd
  @rootfiles = FileList.new
  @make_rootfiles = false
  @resources = FileList.new
  @package_direction = 'rtl'
  @language = 'en'
  @file_map = {}
  @file_map_proc = -> (src_name) {src_name.sub("#{@base_dir.sub(/\/\z/, '')}/", '')}
  @navs = FileList.new
  @media_types = {}
  @spine = FileList.new
  @bindings = {}
end

#rootfile=(rootfile) ⇒ Object



122
123
124
125
# File 'lib/epub/maker/task.rb', line 122

def rootfile=(rootfile)
  rootfiles.unshift rootfile
  rootfile
end