Class: Bridgetown::Resource::Base

Inherits:
Object
  • Object
show all
Includes:
LayoutPlaceable, LiquidRenderable, Localizable, Publishable, Comparable
Defined in:
bridgetown-core/lib/bridgetown-core/resource/base.rb

Overview

rubocop:todo Metrics/ClassLength

Constant Summary collapse

DATE_FILENAME_MATCHER =
%r!^(?>.+/)*?(\d{2,4}-\d{1,2}-\d{1,2})-([^/]*)(\.[^.]+)$!

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Localizable

#all_locales, #localeless_path, #matches_resource?

Methods included from LiquidRenderable

#liquid_engine_configured?, #render_with_liquid?, #yaml_file?

Methods included from LayoutPlaceable

#no_layout?, #place_in_layout?

Methods included from Publishable

#publishable?, #published?

Constructor Details

#initialize(model:) ⇒ Base

Returns a new instance of Base.

Parameters:



39
40
41
42
43
44
45
46
47
48
49
50
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 39

def initialize(model:)
  @model = model
  @site = model.site
  @data = Signalize.signal(
    collection.data? ? HashWithDotAccess::Hash.new : front_matter_defaults
  )
  # we track content subscriptions under the hood numerically…cleans up internal issues
  @content_signal = Signalize.signal(0)
  @slots = []

  trigger_hooks :post_init
end

Instance Attribute Details

#contentString

Returns the resource content minus its layout.

Returns:

  • (String)

    the resource content minus its layout



125
126
127
128
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 125

def content
  @content_signal.value # subscribe for Fast Refresh
  @content
end

#destinationDestination (readonly)

Returns:



13
14
15
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 13

def destination
  @destination
end

#fast_refresh_orderBoolean (readonly)

Returns:

  • (Boolean)


25
26
27
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 25

def fast_refresh_order
  @fast_refresh_order
end

#modelBridgetown::Model::Base (readonly)



16
17
18
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 16

def model
  @model
end

#outputString

Returns:

  • (String)


33
34
35
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 33

def output
  @output
end

#siteBridgetown::Site (readonly)

Returns:



19
20
21
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 19

def site
  @site
end

#slotsArray<Bridgetown::Slot> (readonly)

Returns:



22
23
24
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 22

def slots
  @slots
end

#untransformed_contentString

Returns:

  • (String)


28
29
30
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 28

def untransformed_content
  @untransformed_content
end

Instance Method Details

#<=>(other) ⇒ Integer

Compare this resource against another resource. Comparison is a comparison between the 2 dates or paths of the resources.

Returns:

  • (Integer)

    -1, 0, or +1



320
321
322
323
324
325
326
327
328
329
330
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 320

def <=>(other) # rubocop:todo Metrics/AbcSize
  return nil unless other.respond_to?(:data)

  cmp = if data.date.respond_to?(:to_datetime) && other.data.date.respond_to?(:to_datetime)
          data.date.to_datetime <=> other.data.date.to_datetime
        end

  cmp = data["date"] <=> other.data["date"] if cmp.nil?
  cmp = path <=> other.path if cmp.nil? || cmp.zero?
  cmp
end

#absolute_urlString

Returns:

  • (String)


220
221
222
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 220

def absolute_url
  format_url destination&.absolute_url
end

#around_hook(hook_suffix) ⇒ Object



179
180
181
182
183
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 179

def around_hook(hook_suffix)
  trigger_hooks :"pre_#{hook_suffix}"
  yield
  trigger_hooks :"post_#{hook_suffix}"
end

#as_jsonObject



304
305
306
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 304

def as_json(*)
  to_h
end

#basename_without_extString

Returns:

  • (String)


200
201
202
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 200

def basename_without_ext
  relative_path.basename(".*").to_s
end

#collectionBridgetown::Collection

Collection associated with this resource



55
56
57
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 55

def collection
  model.collection
end

#dataHashWithDotAccess::Hash



103
104
105
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 103

def data
  @data.value
end

#data=(new_data) ⇒ Object

Merges new data into the existing data hash.

Parameters:



110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 110

def data=(new_data)
  if site.config.fast_refresh && write?
    # TODO: investigate if this would be better:
    # @data.value = front_matter_defaults
    mark_for_fast_refresh!
  end

  Signalize.batch do
    @content_signal.value += 1
    @data.value = @data.value.merge(new_data)
  end
  @data.peek
end

#dateObject



239
240
241
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 239

def date
  data["date"] ||= site.time
end

#dispose_of_transform_effectObject



374
375
376
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 374

def dispose_of_transform_effect
  @transform_effect_disposal&.()
end

#extnameString

Returns:

  • (String)


205
206
207
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 205

def extname
  relative_path.extname
end

#front_matter_defaultsHashWithDotAccess::Hash

Loads in any default front matter associated with the resource.



95
96
97
98
99
100
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 95

def front_matter_defaults
  site.frontmatter_defaults.all(
    relative_path.to_s,
    collection.label.to_sym
  ).with_dot_access
end

#idString

Returns:

  • (String)


230
231
232
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 230

def id
  model.origin.id
end

#inspectObject



312
313
314
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 312

def inspect
  "#<#{self.class} #{id}>"
end

#layoutBridgetown::Layout

Layout associated with this resource This will output a warning if the layout can’t be found.

Returns:



63
64
65
66
67
68
69
70
71
72
73
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 63

def layout
  return @layout if @layout
  return if no_layout?

  @layout = site.layouts[data.layout].tap do |layout|
    unless layout
      Bridgetown.logger.warn "Resource:", "Layout '#{data.layout}' " \
                                          "requested via #{relative_path} does not exist."
    end
  end
end

#mark_for_fast_refresh!Object



346
347
348
349
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 346

def mark_for_fast_refresh!
  @fast_refresh_order = site.fast_refresh_ordering
  site.fast_refresh_ordering += 1
end

#next_resourceObject Also known as: next_doc, next



332
333
334
335
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 332

def next_resource
  pos = collection.resources.index { |item| item.equal?(self) }
  collection.resources[pos + 1] if pos && pos < collection.resources.length - 1
end

#output_extString

Returns:

  • (String)


235
236
237
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 235

def output_ext
  destination&.output_ext
end

#pathString

Returns:

  • (String)


215
216
217
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 215

def path
  (model.origin.respond_to?(:original_path) ? model.origin.original_path : relative_path).to_s
end

Returns:

  • (String, nil)


210
211
212
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 210

def permalink
  data&.permalink
end

#prepare_for_fast_refresh!Object

rubocop:todo Metrics



355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 355

def prepare_for_fast_refresh! # rubocop:todo Metrics
  dispose_of_transform_effect
  FileUtils.rm(destination.output_path, force: true) if requires_destination?
  past_values = @data.peek.select do |key|
    key == "categories" || key == "tags" || site.taxonomy_types.keys.any?(key)
  end
  model.attributes = model.origin.read
  read!
  tax_diff = past_values.any? { |k, v| @data.peek[k] != v }

  if tax_diff && !collection.data?
    # If the taxonomy values are different, we should just abort the fast refresh process.
    unmark_for_fast_refresh!
    false
  else
    true
  end
end

#previous_resourceObject Also known as: previous_doc, previous



339
340
341
342
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 339

def previous_resource
  pos = collection.resources.index { |item| item.equal?(self) }
  collection.resources[pos - 1] if pos&.positive?
end

#read!Bridgetown::Resource::Base Also known as: read



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 131

def read!
  self.data = model.data_attributes
  self.content = model.content # could be nil

  unless collection.data?
    self.untransformed_content = content
    normalize_categories_and_tags
    import_taxonomies_from_data
    ensure_default_data
    transformer.execute_inline_ruby!
    set_date_from_string(data.date)
  end

  @destination = Destination.new(self) if requires_destination?

  trigger_hooks :post_read

  self
end

#relationsBridgetown::Resource::Relations



88
89
90
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 88

def relations
  @relations ||= Bridgetown::Resource::Relations.new(self)
end

#relative_pathPathname

The relative path of source file or file-like origin

Returns:

  • (Pathname)


78
79
80
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 78

def relative_path
  model.origin.relative_path
end

#relative_path_basename_without_prefixString

Returns:

  • (String)


186
187
188
189
190
191
192
193
194
195
196
197
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 186

def relative_path_basename_without_prefix
  return_path = Pathname.new("")
  relative_path.each_filename do |filename|
    if matches = DATE_FILENAME_MATCHER.match(filename) # rubocop:disable Lint/AssignmentInCondition
      filename = matches[2] + matches[3]
    end

    return_path += filename unless filename.starts_with?("_")
  end

  (return_path.dirname + return_path.basename(".*")).to_s
end

#relative_urlString

Returns:

  • (String)


225
226
227
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 225

def relative_url
  format_url destination&.relative_url
end

#requires_destination?Boolean Also known as: write?

Returns:

  • (Boolean)


266
267
268
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 266

def requires_destination?
  collection.write? && data.config&.output != false
end

#summaryString

Ask the configured summary extension to output a summary of the content, otherwise return the first line.

Returns:

  • (String)


247
248
249
250
251
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 247

def summary
  return summary_extension_output if respond_to?(:summary_extension_output)

  content.to_s.strip.lines.first.to_s.strip.html_safe
end

#taxonomiesHash<String, Hash<String => Bridgetown::Resource::TaxonomyType, Array<Bridgetown::Resource::TaxonomyTerm>>>

Returns:



255
256
257
258
259
260
261
262
263
264
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 255

def taxonomies
  @taxonomies ||= site.taxonomy_types.values.each_with_object(
    HashWithDotAccess::Hash.new
  ) do |taxonomy, hsh|
    hsh[taxonomy.label] = {
      type: taxonomy,
      terms: [],
    }
  end
end

#to_hObject



289
290
291
292
293
294
295
296
297
298
299
300
301
302
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 289

def to_h
  {
    id:,
    absolute_url:,
    relative_path:,
    relative_url:,
    date:,
    data:,
    taxonomies:,
    untransformed_content:,
    content:,
    output:,
  }
end

#to_jsonObject



308
309
310
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 308

def to_json(...)
  as_json(...).to_json(...)
end

#to_liquidDrops::ResourceDrop

Create a Liquid-understandable version of this resource.

Returns:



285
286
287
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 285

def to_liquid
  @to_liquid ||= Drops::ResourceDrop.new(self)
end

#to_sObject



278
279
280
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 278

def to_s
  output || content || ""
end

#transform!Object

rubocop:todo Metrics/CyclomaticComplexity



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 152

def transform! # rubocop:todo Metrics/CyclomaticComplexity
  internal_error = nil
  @transform_effect_disposal = Signalize.effect do
    if !@fast_refresh_order && @previously_transformed
      self.content = untransformed_content
      @transformer = nil
      mark_for_fast_refresh! if site.config.fast_refresh && write?
      next
    end

    transformer.process! unless collection.data?
    slots.clear
    @previously_transformed = true
  rescue StandardError, SyntaxError => e
    internal_error = e
  end

  raise internal_error if internal_error

  self
end

#transformerBridgetown::Resource::Transformer



83
84
85
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 83

def transformer
  @transformer ||= Bridgetown::Resource::Transformer.new(self)
end

#trigger_hooks(hook_name, *args) ⇒ Object



174
175
176
177
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 174

def trigger_hooks(hook_name, *args)
  Bridgetown::Hooks.trigger collection.label.to_sym, hook_name, self, *args if collection
  Bridgetown::Hooks.trigger :resources, hook_name, self, *args
end

#unmark_for_fast_refresh!Object



351
352
353
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 351

def unmark_for_fast_refresh!
  @fast_refresh_order = nil
end

#write(_dest = nil) ⇒ Object

Write the generated resource file to the destination directory.



272
273
274
275
276
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 272

def write(_dest = nil)
  destination.write(output)
  unmark_for_fast_refresh!
  trigger_hooks(:post_write)
end