Class: Mint::Document

Inherits:
Resource show all
Defined in:
lib/mint/plugins/epub.rb,
lib/mint/document.rb

Overview

Add chapters to document – this is probably not a sustainable pattern for all plugins, but it’s useful here.

Constant Summary collapse

METADATA_DELIM =
"\n\n"

Instance Attribute Summary collapse

Attributes inherited from Resource

#context, #destination, #name, #root, #source, #type

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Resource

#destination_directory, #destination_directory_path, #destination_file, #destination_file_path, #equal?, #renderer=, #root_directory, #root_directory_path, #source_directory, #source_directory_path, #source_file, #source_file_path

Constructor Details

#initialize(source, root: nil, destination: nil, context: nil, name: nil, style_mode: :inline, style_destination: nil, layout: nil, style: nil, template: nil, layout_or_style_or_template: [:template, 'default'], all_files: nil) {|_self| ... } ⇒ Document

Creates a new Mint Document object. Can be block initialized.

Yields:

  • (_self)

Yield Parameters:



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/mint/document.rb', line 11

def initialize(source, 
               root: nil, 
               destination: nil, 
               context: nil, 
               name: nil, 
               style_mode: :inline, 
               style_destination: nil, 
               layout: nil, 
               style: nil, 
               template: nil,
               layout_or_style_or_template: [:template, 'default'],
               all_files: nil,
               &block)
               
  destination = preserve_folder_structure!(source, root, destination)
  
  @all_files = all_files if all_files && all_files.any?

  style_mode = :external if style_destination && style_mode == :inline

  # Loads source and destination, which will be used for
  # all source_* and destination_* virtual attributes.
  super(source, root: root, destination: destination, context: context, name: name)
  self.type = :document

  # Each of these should invoke explicitly defined method
  self.content = source
  self.style_mode = style_mode
  self.style_destination = style_destination

  if layout_or_style_or_template
    type, name = layout_or_style_or_template
    case type
    when :template
      self.template = name
    when :layout
      self.layout = name
    when :style
      self.style = name
    end
  end

  # Individual layout/style options can override the above
  self.layout = layout if layout
  self.style = style if style

  # The template option will override layout and style choices
  self.template = template if template

  # Yield self to block after all other parameters are loaded,
  # so we only have to tweak. (We don't have to give up our
  # defaults or re-test blocks beyond them being tweaked.)
  yield self if block
end

Instance Attribute Details

#layoutObject

Implicit readers are paired with explicit accessors. This allows for processing variables before storing them.



90
91
92
# File 'lib/mint/document.rb', line 90

def layout
  @layout
end

#metadataObject (readonly)

Implicit readers are paired with explicit accessors. This allows for processing variables before storing them.



90
91
92
# File 'lib/mint/document.rb', line 90

def 
  
end

#styleObject

Implicit readers are paired with explicit accessors. This allows for processing variables before storing them.



90
91
92
# File 'lib/mint/document.rb', line 90

def style
  @style
end

#style_destinationObject

Explanation of style_destination:

I’m going to maintain a document’s official style_destination outside of its style object. If a document has no style_destination defined when it needs one, the document will use the original style’s source directory.

This decision eliminates edge cases, including the case where we want to generate, but not move, a document’s style. It also lets us keep style information separate from document-specific information. (Without this separation, funky things happen when you assign a new style template to an existing document – if you had specified a custom style_destination before changing the template, that custom destination would be overridden.)

The style_destination attribute is lazy. It’s exposed via virtual attributes like #style_destination_file.



177
178
179
# File 'lib/mint/document.rb', line 177

def style_destination
  @style_destination
end

#style_modeObject

Explanation of style_destination:

I’m going to maintain a document’s official style_destination outside of its style object. If a document has no style_destination defined when it needs one, the document will use the original style’s source directory.

This decision eliminates edge cases, including the case where we want to generate, but not move, a document’s style. It also lets us keep style information separate from document-specific information. (Without this separation, funky things happen when you assign a new style template to an existing document – if you had specified a custom style_destination before changing the template, that custom destination would be overridden.)

The style_destination attribute is lazy. It’s exposed via virtual attributes like #style_destination_file.



177
178
179
# File 'lib/mint/document.rb', line 177

def style_mode
  @style_mode
end

Class Method Details

.metadata_chunk(text) ⇒ Object



367
368
369
# File 'lib/mint/document.rb', line 367

def (text)
  text.split().first
end

.metadata_from(text) ⇒ Object



371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
# File 'lib/mint/document.rb', line 371

def (text)
   = YAML.load (text)

  case 
  when String
    {}
  when false
    {}
  when nil
    {}
  else
    
  end
rescue Psych::SyntaxError
  {}
rescue Exception
  {}
end

.parse_metadata_from(text) ⇒ Object



390
391
392
393
394
395
396
397
398
399
400
# File 'lib/mint/document.rb', line 390

def (text)
   =  text
  new_text =
    if !.empty?
      text.sub (text) + , ""
    else
      text
    end

  [, new_text]
end

Instance Method Details

#chaptersObject



18
19
20
21
# File 'lib/mint/plugins/epub.rb', line 18

def chapters
  html_document = Nokogiri::HTML::Document.parse render
  EPub.split_on(html_document, "h2").map &:to_s
end

#contentObject

Returns HTML content marked as safe for template rendering



93
94
95
# File 'lib/mint/document.rb', line 93

def content
  @content.html_safe
end

#content=(content) ⇒ void

This method returns an undefined value.

Passes content through a renderer before assigning it to be the Document’s content



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/mint/document.rb', line 103

def content=(content)
  tempfile = Helpers.generate_temp_file! content
  original_content = File.read content

  , text = Document. original_content
  text_with_links = Helpers.transform_markdown_links text
  intermediate_content = Mint.before_render text_with_links, {}

  File.open(tempfile, "w") do |file|
    file << intermediate_content
  end

  @renderer = Mint.renderer tempfile
  @content = @renderer.render
end

#filesObject

Returns information about all files for navigation in some templates (e.g., garden) Available when processing multiple files



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/mint/document.rb', line 281

def files
  return [] unless @all_files
  
  # Get the base directories
  source_base_dir = Pathname.new(root_directory_path).expand_path
  
  # Calculate where the current file will actually be placed
  current_source_path = Pathname.new(source_file_path).expand_path
  current_relative_to_source = current_source_path.relative_path_from(source_base_dir)
  current_html_filename = current_relative_to_source.to_s.gsub(/\.(#{Mint::MARKDOWN_EXTENSIONS.join('|')})$/i, '.html')
  
  dest_base = Pathname.new(root_directory_path).expand_path
  if destination && !destination.empty?
    dest_base = dest_base + destination
  end
  
  current_full_path = dest_base + current_html_filename
  current_destination_dir = current_full_path.dirname
  
  @all_files.map do |file|
    title = extract_title_from_file(file)
    
    # Calculate where this target file will be placed
    file_path = Pathname.new(file).expand_path
    relative_to_source = file_path.relative_path_from(source_base_dir)
    html_filename = relative_to_source.to_s.gsub(/\.(#{Mint::MARKDOWN_EXTENSIONS.join('|')})$/i, '.html')
    
    target_full_path = dest_base + html_filename
    
    # Calculate the relative path from the current file's destination directory to the target file
    relative_link = target_full_path.relative_path_from(current_destination_dir)
    
    {
      source_path: relative_to_source.to_s,
      html_path: relative_link.to_s,
      title: title,
      depth: relative_to_source.to_s.count('/')
    }
  end.sort_by {|f| f[:source_path] }
end

#inline_stylesObject

Parses styles defined in YAML metadata in content, including it in output CSS style

TODO: Implement injection of these styles



275
276
277
# File 'lib/mint/document.rb', line 275

def inline_styles
  CSS.parse()
end

#inline_stylesheetObject

Returns the rendered CSS content for inline inclusion



239
240
241
# File 'lib/mint/document.rb', line 239

def inline_stylesheet
  self.style.render
end

#original_stylesheet_tagsObject

Generates stylesheet link tags for original mode Links directly to original CSS files without processing



258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/mint/document.rb', line 258

def original_stylesheet_tags
  return "" unless self.style&.template_path
  
  main_css_path = self.style.template_path
  html_output_path = self.output_file
  
  # Only process .css files
  return "" unless File.extname(main_css_path) == '.css'
  
  css_file_paths = CssParser.resolve_css_files(main_css_path, html_output_path)
  CssParser.generate_link_tags(css_file_paths)
end

#publish!(opts = {}) ⇒ Object

Writes all rendered content where a) possible, b) required, and c) specified. Outputs to specified file.



74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/mint/document.rb', line 74

def publish!(opts={})
  options = { :render_style => true }.merge(opts)
  super

  if @style_mode == :external && options[:render_style]
    FileUtils.mkdir_p style_destination_directory
    File.open(self.style_destination_file, "w+") do |f|
      f << self.style.render
    end
  end

  Mint.after_publish(self, opts)
end

#render(args = {}) ⇒ Object

Renders content in the context of layout and returns as a String.



67
68
69
70
# File 'lib/mint/document.rb', line 67

def render(args={})
  intermediate_content = layout.render self, args
  Mint.after_render(intermediate_content, {})
end

#style_destination_directoryString

Exposes style_destination directory as a String.



223
224
225
# File 'lib/mint/document.rb', line 223

def style_destination_directory
  style_destination_directory_path.to_s
end

#style_destination_directory_pathPathname

Exposes style_destination directory as a Pathname object.



216
217
218
# File 'lib/mint/document.rb', line 216

def style_destination_directory_path
  style_destination_file_path.dirname
end

#style_destination_fileString

Exposes style_destination as a String.



209
210
211
# File 'lib/mint/document.rb', line 209

def style_destination_file
  style_destination_file_path.to_s
end

#style_destination_file_pathPathname

Exposes style_destination as a Pathname object.



195
196
197
198
199
200
201
202
203
204
# File 'lib/mint/document.rb', line 195

def style_destination_file_path
  if style_destination
    path = Pathname.new style_destination
    dir = path.absolute? ?
      path : destination_directory_path + path
    dir + style.name
  else
    style.destination_file_path
  end
end

#stylesheetObject

Returns a relative path from the document to its stylesheet. Can be called directly from inside a layout template.



231
232
233
234
235
236
# File 'lib/mint/document.rb', line 231

def stylesheet
  tmp_style_dir = Mint.path_for_scope(:user) + "tmp"
  tmp_style_file = tmp_style_dir + File.basename(style.name)
  Helpers.normalize_path(tmp_style_file.to_s,
                         self.destination_directory).to_s
end

#stylesheet_tagObject

Returns either inline CSS or stylesheet link based on style mode Use this helper in layouts instead of stylesheet or inline_stylesheet directly



245
246
247
248
249
250
251
252
253
254
# File 'lib/mint/document.rb', line 245

def stylesheet_tag
  case @style_mode
  when :external
    "<link rel=\"stylesheet\" href=\"#{stylesheet}\">".html_safe
  when :original
    original_stylesheet_tags.html_safe
  else # :inline (default)
    "<style>#{self.style.render}</style>".html_safe
  end
end

#template=(template) ⇒ Object

Overrides layout and style settings with named template.



153
154
155
156
157
158
# File 'lib/mint/document.rb', line 153

def template=(template)
  if template
    self.layout = template
    self.style = template
  end
end