Class: Epuber::Compiler::FileTypes::XHTMLFile

Inherits:
SourceFile show all
Defined in:
lib/epuber/compiler/file_types/xhtml_file.rb

Direct Known Subclasses

BadeFile

Instance Attribute Summary collapse

Attributes inherited from SourceFile

#abs_source_path, #file_request, #source_path

Attributes inherited from AbstractFile

#compilation_context, #destination_path, #final_destination_path, #group, #path_type, #pkg_destination_path, #properties

Instance Method Summary collapse

Methods inherited from SourceFile

#default_file_copy, #destination_file_exist?, #destination_file_up_to_date?, #find_dependencies, #properties, resolve_relative_file, #source_file_up_to_date?, #update_metadata!, #write_compiled, #write_processed

Methods inherited from AbstractFile

#==, file_copy!, write_to_file, write_to_file!, write_to_file?

Constructor Details

#initialize(source_path) ⇒ XHTMLFile

Returns a new instance of XHTMLFile.



23
24
25
26
27
28
# File 'lib/epuber/compiler/file_types/xhtml_file.rb', line 23

def initialize(source_path)
  super

  self.global_ids = []
  self.global_links = []
end

Instance Attribute Details

#global_idsArray<String>

Returns:

  • (Array<String>)


17
18
19
# File 'lib/epuber/compiler/file_types/xhtml_file.rb', line 17

def global_ids
  @global_ids
end

Returns:

  • (Array<String>)


21
22
23
# File 'lib/epuber/compiler/file_types/xhtml_file.rb', line 21

def global_links
  @global_links
end

#toc_itemEpuber::Book::TocItem



13
14
15
# File 'lib/epuber/compiler/file_types/xhtml_file.rb', line 13

def toc_item
  @toc_item
end

Instance Method Details

#common_process(content, compilation_context) ⇒ String

Returns new xhtml string.

Parameters:

Returns:

  • (String)

    new xhtml string



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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/epuber/compiler/file_types/xhtml_file.rb', line 96

def common_process(content, compilation_context)
  target = compilation_context.target
  book = compilation_context.book
  file_resolver = compilation_context.file_resolver

  xhtml_doc, errors = UI.print_step_processing_time('parsing XHTML file') do
    XHTMLProcessor.xml_doc_from_str_with_errors(content, source_path)
  end

  process_nokogiri_errors(errors) if compilation_context.release_build && xhtml_doc.errors.count.positive?

  UI.print_step_processing_time('adding missing elements') do
    XHTMLProcessor.add_missing_root_elements(xhtml_doc, book.title, target.epub_version)
  end

  # resolve links to files, add other linked resources and compute correct path
  UI.print_step_processing_time('resolving links') do
    XHTMLProcessor.resolve_links(xhtml_doc, destination_path, file_resolver.dest_finder)
  end
  UI.print_step_processing_time('resolving image resources') do
    XHTMLProcessor.resolve_images(xhtml_doc, destination_path, file_resolver)
  end
  UI.print_step_processing_time('resolving scripts') do
    XHTMLProcessor.resolve_scripts(xhtml_doc, destination_path, file_resolver)
  end
  UI.print_step_processing_time('resolving stylesheets') do
    XHTMLProcessor.resolve_stylesheets(xhtml_doc, destination_path, file_resolver)
  end

  UI.print_step_processing_time('adding default things') do
    XHTMLProcessor.add_styles(xhtml_doc, default_styles(target, file_resolver))
    XHTMLProcessor.add_scripts(xhtml_doc, default_scripts(target, file_resolver))

    XHTMLProcessor.add_viewport(xhtml_doc, target.default_viewport) unless target.default_viewport.nil?
  end

  XHTMLProcessor.resolve_mathml_namespace(xhtml_doc)

  UI.print_step_processing_time('investigating properties') do
    properties << :remote_resources if XHTMLProcessor.using_remote_resources?(xhtml_doc)
    properties << :scripted if XHTMLProcessor.using_javascript?(xhtml_doc)
    properties << :mathml if XHTMLProcessor.using_mathml?(xhtml_doc)
  end

  xhtml_string = UI.print_step_processing_time('converting to XHTML') do
    xhtml_doc.to_s
  end

  # perform transformations
  compilation_context.perform_plugin_things(Transformer, :result_text_xhtml_string) do |transformer|
    xhtml_string = transformer.call(final_destination_path, xhtml_string, compilation_context)
  end

  # perform custom validation
  if compilation_context.should_check
    compilation_context.perform_plugin_things(Checker, :result_text_xhtml_string) do |checker|
      checker.call(final_destination_path, xhtml_string, compilation_context)
    end
  end

  if xhtml_string.include?('="$')
    xhtml_doc = XHTMLProcessor.xml_document_from_string(xhtml_string, final_destination_path)
    self.global_ids = XHTMLProcessor.find_global_ids(xhtml_doc)
    self.global_links = XHTMLProcessor.find_global_links(xhtml_doc)
  end

  xhtml_string
end

#default_scripts(target, file_resolver) ⇒ Array<String>

Returns list of paths to styles relative to this file.

Parameters:

Returns:

  • (Array<String>)

    list of paths to styles relative to this file



51
52
53
54
55
56
57
58
59
60
# File 'lib/epuber/compiler/file_types/xhtml_file.rb', line 51

def default_scripts(target, file_resolver)
  default_scripts = target.default_scripts.map do |default_style_request|
    Array(file_resolver.file_from_request(default_style_request))
  end.flatten

  dirname = Pathname.new(File.dirname(final_destination_path))
  default_scripts.map do |style|
    Pathname.new(style.final_destination_path).relative_path_from(dirname).to_s
  end
end

#default_styles(target, file_resolver) ⇒ Array<String>

Returns list of paths to styles relative to this file.

Parameters:

Returns:

  • (Array<String>)

    list of paths to styles relative to this file



35
36
37
38
39
40
41
42
43
44
# File 'lib/epuber/compiler/file_types/xhtml_file.rb', line 35

def default_styles(target, file_resolver)
  default_styles = target.default_styles.map do |default_style_request|
    Array(file_resolver.file_from_request(default_style_request))
  end.flatten

  dirname = Pathname.new(File.dirname(final_destination_path))
  default_styles.map do |style|
    Pathname.new(style.final_destination_path).relative_path_from(dirname).to_s
  end
end

#load_source(compilation_context) ⇒ Object

Parameters:



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/epuber/compiler/file_types/xhtml_file.rb', line 64

def load_source(compilation_context)
  xhtml_content = File.read(abs_source_path)

  compilation_context.perform_plugin_things(Transformer, :source_text_file) do |transformer|
    xhtml_content = transformer.call(abs_source_path, xhtml_content, compilation_context)
  end

  # perform custom validation
  if compilation_context.should_check
    compilation_context.perform_plugin_things(Checker, :source_text_file) do |checker|
      checker.call(abs_source_path, xhtml_content, compilation_context)
    end
  end

  self.class.write_to_file(xhtml_content, abs_source_path) if compilation_context.should_write

  xhtml_content
end

#process(compilation_context) ⇒ Object



167
168
169
# File 'lib/epuber/compiler/file_types/xhtml_file.rb', line 167

def process(compilation_context)
  write_processed(common_process(load_source(compilation_context), compilation_context))
end

#process_global_ids(_compilation_context, global_ids) ⇒ Object

Parameters:



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/epuber/compiler/file_types/xhtml_file.rb', line 174

def process_global_ids(_compilation_context, global_ids)
  return if self.global_ids.empty? && global_links.empty?

  xhtml_doc = XHTMLProcessor.xml_document_from_string(File.read(final_destination_path), final_destination_path)

  XHTMLProcessor.find_global_ids_nodes(xhtml_doc).each do |node|
    id = node['id']
    node['id'] = id[1..-1]
  end

  XHTMLProcessor.find_global_links_nodes(xhtml_doc).each do |node|
    href = node['href'][1..-1]

    dest_file = global_ids[href]
    if dest_file
      rel_path = Pathname(dest_file.final_destination_path.unicode_normalize)
                 .relative_path_from(Pathname(File.dirname(final_destination_path.unicode_normalize))).to_s

      node['href'] = "#{rel_path}##{href}"
    else
      message = "Can't find global id '#{href}' from link in file #{source_path}"
      location = Epuber::Location.new(path: final_destination_path, lineno: node.line)
      UI.error(message, location: location)
    end
  end

  write_processed(xhtml_doc.to_s)
end

#process_nokogiri_errors(errors) ⇒ Object

Parameters:



85
86
87
88
89
# File 'lib/epuber/compiler/file_types/xhtml_file.rb', line 85

def process_nokogiri_errors(errors)
  errors.each do |problem|
    UI.warning(problem, location: self)
  end
end