Class: Bridgetown::Resource::Base

Inherits:
Object
  • Object
show all
Includes:
LayoutPlaceable, Localizable, Publishable, Bridgetown::RodaCallable, 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 LayoutPlaceable

#no_layout?, #place_in_layout?

Methods included from Publishable

#publishable?, #published?

Methods included from Bridgetown::RodaCallable

===

Constructor Details

#initialize(model:) ⇒ Base

Returns a new instance of Base.

Parameters:



43
44
45
46
47
48
49
50
51
52
53
54
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 43

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



122
123
124
125
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 122

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

#destinationDestination (readonly)

Returns:



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

def destination
  @destination
end

#fast_refresh_orderBoolean (readonly)

Returns:

  • (Boolean)


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

def fast_refresh_order
  @fast_refresh_order
end

#modelBridgetown::Model::Base (readonly)



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

def model
  @model
end

#outputString

Returns:

  • (String)


37
38
39
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 37

def output
  @output
end

#roda_appRoda

Returns:



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

def roda_app
  @roda_app
end

#siteBridgetown::Site (readonly)

Returns:



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

def site
  @site
end

#slotsArray<Bridgetown::Slot> (readonly)

Returns:



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

def slots
  @slots
end

#untransformed_contentString

Returns:

  • (String)


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

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



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

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

  cmp = if data.date.respond_to?(:to_time) && other.data.date.respond_to?(:to_time)
          data.date.to_time <=> other.data.date.to_time
        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)


222
223
224
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 222

def absolute_url
  @absolute_url ||= format_url(destination&.absolute_url)
end

#around_hook(hook_suffix) ⇒ Object



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

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

#as_jsonObject



306
307
308
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 306

def as_json(*)
  to_h
end

#basename_without_extString

Returns:

  • (String)


202
203
204
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 202

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

#callString

Transforms the resource and returns the full output

Returns:

  • (String)


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

def call(*) = transform!.output

#collectionBridgetown::Collection

Collection associated with this resource



59
60
61
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 59

def collection
  model.collection
end

#dataHashWithDotAccess::Hash



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

def data
  @data.value
end

#data=(new_data) ⇒ Object

Merges new data into the existing data hash.

Parameters:



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

def data=(new_data)
  mark_for_fast_refresh! if site.config.fast_refresh && write?

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

#dateObject



241
242
243
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 241

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

#deconstruct_keysObject



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

def deconstruct_keys(...)
  @data.value.deconstruct_keys(...)
end

#dispose_of_transform_effectObject



384
385
386
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 384

def dispose_of_transform_effect
  @transform_effect_disposal&.()
end

#extnameString

Returns:

  • (String)


207
208
209
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 207

def extname
  relative_path.extname
end

#front_matter_defaultsHashWithDotAccess::Hash

Loads in any default front matter associated with the resource.



99
100
101
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 99

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

#idString

Returns:

  • (String)


232
233
234
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 232

def id
  model.origin.id
end

#inspectObject



314
315
316
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 314

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:



67
68
69
70
71
72
73
74
75
76
77
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 67

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



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

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



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

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)


237
238
239
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 237

def output_ext
  destination&.output_ext
end

#pathString

Returns:

  • (String)


217
218
219
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 217

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

Returns:

  • (String, nil)


212
213
214
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 212

def permalink
  data&.permalink
end

#prepare_for_fast_refresh!Object

rubocop:todo Metrics, Naming/PredicateMethod



361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 361

def prepare_for_fast_refresh! # rubocop:todo Metrics, Naming/PredicateMethod
  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
  origin_data = model.origin.read
  correct_locale = origin_data["locale"] || origin_data[:locale] || data.locale
  model.attributes = origin_data
  model.attributes.locale = correct_locale.to_s == "multi" ? data.locale : correct_locale
  @relative_url = @absolute_url = nil # wipe memoizations
  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



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

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



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

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



92
93
94
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 92

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

#relative_pathPathname

The relative path of source file or file-like origin

Returns:

  • (Pathname)


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

def relative_path
  model.origin.relative_path
end

#relative_path_basename_without_prefixString

Returns:

  • (String)


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

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)


227
228
229
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 227

def relative_url
  @relative_url ||= format_url(destination&.relative_url)
end

#requires_destination?Boolean Also known as: write?

Returns:

  • (Boolean)


268
269
270
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 268

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)


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

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:



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

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



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

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

#to_jsonObject



310
311
312
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 310

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

#to_liquidDrops::ResourceDrop

Create a Liquid-understandable version of this resource.

Returns:



287
288
289
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 287

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

#to_sObject



280
281
282
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 280

def to_s
  output || content || ""
end

#transform!Object

rubocop:todo Metrics/CyclomaticComplexity



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

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



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

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

#trigger_hooks(hook_name) ⇒ Object



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

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

#unmark_for_fast_refresh!Object



357
358
359
# File 'bridgetown-core/lib/bridgetown-core/resource/base.rb', line 357

def unmark_for_fast_refresh!
  @fast_refresh_order = nil
end

#write(_dest = nil) ⇒ Object

Write the generated resource file to the destination directory.



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

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